wine-d3d9.patch 202 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786
  1. From f8574ff8a8c64fe6ab7a4399eb0d693e926f45d1 Mon Sep 17 00:00:00 2001
  2. From: Nick Sarnie <commendsarnex@gmail.com>
  3. Date: Sun, 5 Nov 2017 22:31:07 -0500
  4. Subject: [PATCH 2/2] Wine D3D9
  5. Signed-off-by: Nick Sarnie <commendsarnex@gmail.com>
  6. ---
  7. configure.ac | 188 ++++
  8. dlls/d3d9-nine/Makefile.in | 15 +
  9. dlls/d3d9-nine/d3d9-nine.spec | 14 +
  10. dlls/d3d9-nine/d3d9_main.c | 173 ++++
  11. dlls/d3d9-nine/d3dadapter9.c | 898 +++++++++++++++++++
  12. dlls/d3d9-nine/d3dadapter9.h | 32 +
  13. dlls/d3d9-nine/device_wrap.c | 500 +++++++++++
  14. dlls/d3d9-nine/device_wrap.h | 26 +
  15. dlls/d3d9-nine/dri3.c | 1426 ++++++++++++++++++++++++++++++
  16. dlls/d3d9-nine/dri3.h | 91 ++
  17. dlls/d3d9-nine/present.c | 1748 +++++++++++++++++++++++++++++++++++++
  18. dlls/d3d9-nine/present.h | 40 +
  19. dlls/d3d9-nine/shader_validator.c | 88 ++
  20. dlls/d3d9-nine/shader_validator.h | 29 +
  21. dlls/d3d9-nine/version.rc | 26 +
  22. dlls/d3d9-nine/wndproc.c | 277 ++++++
  23. dlls/d3d9-nine/wndproc.h | 41 +
  24. 17 files changed, 5612 insertions(+)
  25. create mode 100644 dlls/d3d9-nine/Makefile.in
  26. create mode 100644 dlls/d3d9-nine/d3d9-nine.spec
  27. create mode 100644 dlls/d3d9-nine/d3d9_main.c
  28. create mode 100644 dlls/d3d9-nine/d3dadapter9.c
  29. create mode 100644 dlls/d3d9-nine/d3dadapter9.h
  30. create mode 100644 dlls/d3d9-nine/device_wrap.c
  31. create mode 100644 dlls/d3d9-nine/device_wrap.h
  32. create mode 100644 dlls/d3d9-nine/dri3.c
  33. create mode 100644 dlls/d3d9-nine/dri3.h
  34. create mode 100644 dlls/d3d9-nine/present.c
  35. create mode 100644 dlls/d3d9-nine/present.h
  36. create mode 100644 dlls/d3d9-nine/shader_validator.c
  37. create mode 100644 dlls/d3d9-nine/shader_validator.h
  38. create mode 100644 dlls/d3d9-nine/version.rc
  39. create mode 100644 dlls/d3d9-nine/wndproc.c
  40. create mode 100644 dlls/d3d9-nine/wndproc.h
  41. diff --git a/configure.ac b/configure.ac
  42. index 7a8fcc4987..0f2a45f336 100644
  43. --- a/configure.ac
  44. +++ b/configure.ac
  45. @@ -67,6 +67,14 @@ AC_ARG_WITH(openal, AS_HELP_STRING([--without-openal],[do not use OpenAL]),
  46. AC_ARG_WITH(opencl, AS_HELP_STRING([--without-opencl],[do not use OpenCL]),
  47. [if test "x$withval" = "xno"; then ac_cv_header_CL_cl_h=no; ac_cv_header_OpenCL_opencl_h=no; fi])
  48. AC_ARG_WITH(opengl, AS_HELP_STRING([--without-opengl],[do not use OpenGL]))
  49. +AC_ARG_WITH(d3d9-nine, AS_HELP_STRING([--without-d3d9-nine],[do not build d3d9-nine.dll (Gallium Nine support)]),
  50. + [], [with_d3d9_nine=auto])
  51. +AC_ARG_WITH(d3d9-nine-module, AS_HELP_STRING([--with-d3d9-nine-module],
  52. + [Gallium Nine module location. Can be 'manual' (path to be filled in a register), 'auto' (default. use pkgconfig to detect the location) or a path]),
  53. + [], [with_d3d9_nine_module=auto])
  54. +AC_ARG_WITH(d3d9-nine-headers-path, AS_HELP_STRING([--with-d3d9-nine-headers-path],
  55. + [Gallium Nine headers location. Can be 'auto' (default. use pkgconfig to detect the location) or a path]),
  56. + [], [with_d3d9_nine_headers_path=auto])
  57. AC_ARG_WITH(osmesa, AS_HELP_STRING([--without-osmesa],[do not use the OSMesa library]))
  58. AC_ARG_WITH(oss, AS_HELP_STRING([--without-oss],[do not use the OSS sound support]))
  59. AC_ARG_WITH(pcap, AS_HELP_STRING([--without-pcap],[do not use the Packet Capture library]),
  60. @@ -391,6 +399,8 @@ AC_CHECK_LIB(ossaudio,_oss_ioctl)
  61. AC_SUBST(OPENGL_LIBS,"")
  62. +AC_SUBST(D3D9NINE_LIBS,"")
  63. +
  64. dnl **** Check for header files ****
  65. AC_SYS_LARGEFILE()
  66. @@ -1248,6 +1258,183 @@ OpenGL and Direct3D won't be supported.])
  67. WINE_NOTICE_WITH(va,[test "x$ac_cv_lib_soname_va" = "x" -o "x$ac_cv_lib_soname_va_x11" = "x" -o "x$ac_cv_lib_soname_va_drm" = "x"],
  68. [libva ${notice_platform}development files not found, GPU video acceleration won't be supported.])
  69. + dnl Check for d3d9-nine support
  70. + if test "x$with_d3d9_nine" = "xauto" && (test "x$with_d3d9_nine_module" = "xauto" || test "x$with_d3d9_nine_headers_path" = "xauto")
  71. + then
  72. + AC_MSG_CHECKING([whether d3dadapter9 package (Gallium Nine) is present])
  73. + D3DADAPTER9_MODULEDIR=`$PKG_CONFIG --variable=moduledir d3dadapter9 2>/dev/null`
  74. + D3DADAPTER9_LEGACY_MODULEDIR=`$PKG_CONFIG --variable=moduledir d3d 2>/dev/null`
  75. + if test "x$D3DADAPTER9_MODULEDIR" = "x" -a "x$D3DADAPTER9_LEGACY_MODULEDIR" = "x"
  76. + then
  77. + AC_MSG_RESULT([no, disabling support])
  78. + with_d3d9_nine=no
  79. + else
  80. + AC_MSG_RESULT([yes])
  81. + fi
  82. + fi
  83. +
  84. + if test "x$with_d3d9_nine" != "xno"
  85. + then
  86. + AC_MSG_NOTICE([Checking for d3dadapter9 library dependencies])
  87. + D3D9NINE_LIBS=""
  88. + D3D9NINE_MISSING_LIBS=""
  89. + AC_CHECK_LIB(xcb,xcb_request_check,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lxcb"])])
  90. + test "x$ac_cv_lib_xcb_xcb_request_check" != xyes && D3D9NINE_MISSING_LIBS="libxcb "
  91. + AC_CHECK_LIB(xcb-dri3,xcb_dri3_open,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lxcb-dri3"])])
  92. + test "x$ac_cv_lib_xcb_dri3_xcb_dri3_open" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libxcb-dri3 "
  93. + AC_CHECK_LIB(xcb-present,xcb_present_notify_msc,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lxcb-present"])])
  94. + test "x$ac_cv_lib_xcb_present_xcb_present_notify_msc" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libxcb-present "
  95. + AC_CHECK_LIB(xcb-xfixes,xcb_xfixes_create_region,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lxcb-xfixes"])])
  96. + test "x$ac_cv_lib_xcb_xfixes_xcb_xfixes_create_region" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libxcb-xfixes "
  97. + AC_CHECK_LIB(X11-xcb,XGetXCBConnection,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lX11-xcb"])])
  98. + test "x$ac_cv_lib_X11_xcb_XGetXCBConnection" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libX11-xcb "
  99. + AC_CHECK_LIB(X11,XOpenDisplay,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lX11"])])
  100. + test "x$ac_cv_lib_X11_XOpenDisplay" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libX11 "
  101. + AC_CHECK_LIB(Xext,XextRemoveDisplay,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lXext"])])
  102. + test "x$ac_cv_lib_Xext_XextRemoveDisplay" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libXext "
  103. + # libs for the dri2 fallback
  104. + AC_CHECK_LIB(GL,glGenFramebuffers,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lGL"])])
  105. + test "x$ac_cv_lib_GL_glGenFramebuffers" != xyes && D3D9NINE_MISSING_LIBS="libGL "
  106. + AC_CHECK_LIB(EGL,eglCreateContext,[AC_SUBST(D3D9NINE_LIBS,["$D3D9NINE_LIBS -lEGL"])])
  107. + test "x$ac_cv_lib_EGL_eglCreateContext" != xyes && D3D9NINE_MISSING_LIBS="${D3D9NINE_MISSING_LIBS}libEGL"
  108. +
  109. + if test "x$D3D9NINE_MISSING_LIBS" != x
  110. + then
  111. + if test "x$with_d3d9_nine" = "xyes"
  112. + then
  113. + AC_MSG_ERROR([Missing libraries to build d3d9-nine.dll: $D3D9NINE_MISSING_LIBS])
  114. + else
  115. + AC_MSG_NOTICE([Missing libraries to build d3d9-nine.dll: $D3D9NINE_MISSING_LIBS . disabling support])
  116. + with_d3d9_nine=no
  117. + fi
  118. + fi
  119. + fi
  120. +
  121. + if test "x$with_d3d9_nine" != "xno"
  122. + then
  123. + AC_MSG_NOTICE([Checking d3dadapter9 header dependencies])
  124. + D3D9NINE_MISSING_HEADERS=""
  125. + AC_CHECK_HEADERS([X11/Xlib-xcb.h xcb/dri3.h xcb/present.h X11/Xutil.h X11/Xlib.h pthread.h])
  126. + test "x$ac_cv_header_X11_Xlib_xcb_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/Xlib-xcb.h "
  127. + test "x$ac_cv_header_xcb_dri3_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}xcb/dri3.h "
  128. + test "x$ac_cv_header_xcb_present_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}xcb/present.h "
  129. + test "x$ac_cv_header_X11_Xutil_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/Xutil.h "
  130. + test "x$ac_cv_header_X11_Xlib_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/Xlib.h "
  131. + test "x$ac_cv_header_pthread_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}pthread.h "
  132. + # headers for the dri2 fallback
  133. + AC_CHECK_HEADERS([X11/Xmd.h X11/Xlibint.h X11/extensions/dri2tokens.h X11/extensions/dri2proto.h X11/extensions/extutil.h GL/gl.h GL/glext.h EGL/egl.h EGL/eglext.h libdrm/drm_fourcc.h libdrm/drm.h],
  134. + [],[],[[
  135. +#include <X11/Xlibint.h>
  136. +#include <X11/extensions/dri2tokens.h>
  137. +#include <GL/gl.h>
  138. +#include <EGL/egl.h>
  139. +]])
  140. + test "x$ac_cv_header_X11_Xmd_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/Xmd.h "
  141. + test "x$ac_cv_header_X11_Xlibint_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/Xlibint.h "
  142. + test "x$ac_cv_header_X11_extensions_dri2tokens_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/extensions/dri2tokens.h "
  143. + test "x$ac_cv_header_X11_extensions_dri2proto_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/extensions/dri2proto.h "
  144. + test "x$ac_cv_header_X11_extensions_extutil_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}X11/extensions/extutil.h "
  145. + test "x$ac_cv_header_GL_gl_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}GL/gl.h "
  146. + test "x$ac_cv_header_GL_glext_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}GL/glext.h "
  147. + test "x$ac_cv_header_EGL_egl_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}EGL/egl.h "
  148. + test "x$ac_cv_header_EGL_eglext_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}EGL/eglext.h "
  149. + test "x$ac_cv_header_libdrm_drm_fourcc_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}libdrm/drm_fourcc.h "
  150. + test "x$ac_cv_header_libdrm_drm_h" != xyes && D3D9NINE_MISSING_HEADERS="${D3D9NINE_MISSING_HEADERS}libdrm/drm.h "
  151. + if test "x$D3D9NINE_MISSING_HEADERS" != x
  152. + then
  153. + if test "x$with_d3d9_nine" = "xyes"
  154. + then
  155. + AC_MSG_ERROR([Missing headers to build d3d9-nine.dll: $D3D9NINE_MISSING_HEADERS])
  156. + else
  157. + AC_MSG_NOTICE([Missing headers to build d3d9-nine.dll: $D3D9NINE_MISSING_HEADERS . disabling support])
  158. + with_d3d9_nine=no
  159. + fi
  160. + fi
  161. + fi
  162. +
  163. + if test "x$with_d3d9_nine" != "xno"
  164. + then
  165. + # d3d9-nine.dll will be built and an option to use it
  166. + # added. The module path can always be overriden by
  167. + # a wine registry setting. If the module isn't found
  168. + # at execution time, the dll will refuse to load and
  169. + # print an error message to the user.
  170. + AC_DEFINE(HAVE_D3D9NINE, 1, [Whether d3d9-nine.dll is built])
  171. + # default: use pkgconfig to find the gallium nine module.
  172. + # Check the module is there.
  173. + if test "x$with_d3d9_nine_module" = "xauto"
  174. + then
  175. + D3DADAPTER9_MODULEDIR=`$PKG_CONFIG --variable=moduledir d3dadapter9 2>/dev/null`
  176. + if test "x$D3DADAPTER9_MODULEDIR" = x
  177. + then
  178. + # legacy path
  179. + D3DADAPTER9_MODULEDIR=`$PKG_CONFIG --variable=moduledir d3d 2>/dev/null`
  180. + if test "x$D3DADAPTER9_MODULEDIR" = x
  181. + then
  182. + AC_MSG_ERROR([pkg-config couldn't find Gallium Nine module])
  183. + fi
  184. + fi
  185. + AC_DEFINE_UNQUOTED(D3D9NINE_MODULEPATH, ["`echo ${D3DADAPTER9_MODULEDIR}/d3dadapter9.so.1`"], [Gallium Nine module path])
  186. + # Check module
  187. + CPPFLAGSBAK=$CPPFLAGS
  188. + # link against libdl
  189. + CPPFLAGS="$CPPFLAGS -Wl,--no-as-needed -ldl"
  190. +
  191. + AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <dlfcn.h>
  192. +#include <stdlib.h>]],[[void *handle = dlopen("${D3DADAPTER9_MODULEDIR}/d3dadapter9.so.1", RTLD_GLOBAL | RTLD_NOW);
  193. +exit((handle && dlsym(handle, "D3DAdapter9GetProc")) ? 0 : 1)]])],
  194. + [echo "d3dadapter9.so.1 found at '${D3DADAPTER9_MODULEDIR}/d3dadapter9.so.1'"],
  195. + [AC_MSG_ERROR([Couldn't load Gallium nine module at '${D3DADAPTER9_MODULEDIR}/d3dadapter9.so.1' (found by pkg-config)])])
  196. + CPPFLAGS=$CPPFLAGSBAK
  197. + else
  198. + # Manual : do not feed any path, the wine registry will have
  199. + # to be used to pass a path. Useful for wine builds
  200. + # that are distributed and will run on different
  201. + # distros.
  202. + # Else feed a path directly. Useful for distro maintainers who
  203. + # know where the package would be installed, but don't have
  204. + # it installed on their build.
  205. + # Don't check if the module is there.
  206. + if test "x$with_d3d9_nine_module" != "xmanual"
  207. + then
  208. + AC_DEFINE_UNQUOTED(D3D9NINE_MODULEPATH, ["`echo ${with_d3d9_nine_module}`"], [Gallium Nine module path])
  209. + fi
  210. + fi
  211. +
  212. + # by default the headers are found with pkgconfig,
  213. + # but it is possible to pass a path to a specific directory.
  214. + # that directory must contain a d3dadapter directory
  215. + # with d3dadapter9.h, drm.h and present.h
  216. + if test "x$with_d3d9_nine_headers_path" = "xauto"
  217. + then
  218. + AC_PROG_SED
  219. + D3DADAPTER9_INCLUDEDIR=`$PKG_CONFIG --variable=includedir d3dadapter9 2>/dev/null`
  220. + D3DADAPTER9_MAJOR=`$PKG_CONFIG --modversion d3dadapter9 2>/dev/null | $SED -n 's/\([[^\.]]*\)\..*$/\1/p'`
  221. + if test "x$D3DADAPTER9_INCLUDEDIR" = x
  222. + then
  223. + # legacy path
  224. + D3DADAPTER9_INCLUDEDIR=`$PKG_CONFIG --variable=includedir d3d 2>/dev/null`
  225. + D3DADAPTER9_MAJOR=`$PKG_CONFIG --modversion d3d 2>/dev/null | $SED -n 's/\([[^\.]]*\)\..*$/\1/p'`
  226. + if test "x$D3DADAPTER9_INCLUDEDIR" = x
  227. + then
  228. + AC_MSG_ERROR([pkg-config couldn't find Gallium Nine headers])
  229. + fi
  230. + fi
  231. + # check major version of package. The major version number guarantees header compatibility.
  232. + if test "x$D3DADAPTER9_MAJOR" != x1
  233. + then
  234. + AC_MSG_ERROR([pkg-config found Gallium Nine Module and Headers, but version is incompatible])
  235. + fi
  236. + else
  237. + D3DADAPTER9_INCLUDEDIR=`echo ${with_d3d9_nine_headers_path}`
  238. + fi
  239. + AC_DEFINE_UNQUOTED(D3D9NINE_HEADERS_CFLAGS, ["`echo -I${D3DADAPTER9_INCLUDEDIR}`"], [Gallium Nine headers cflags])
  240. +
  241. + AC_DEFINE(D3D9NINE_DRI2, 1, [Whether d3d9-nine DRI2 fallback is compiled])
  242. + else
  243. + enable_d3d9_nine=${enable_d3d9_nine:-no}
  244. + fi
  245. +
  246. CPPFLAGS="$ac_save_CPPFLAGS"
  247. else
  248. X_CFLAGS=""
  249. @@ -3127,6 +3314,7 @@ WINE_CONFIG_DLL(d3d8,,[implib])
  250. WINE_CONFIG_TEST(dlls/d3d8/tests)
  251. WINE_CONFIG_DLL(d3d9,,[implib])
  252. WINE_CONFIG_TEST(dlls/d3d9/tests)
  253. +WINE_CONFIG_DLL(d3d9-nine,,[implib])
  254. WINE_CONFIG_DLL(d3dcompiler_33)
  255. WINE_CONFIG_DLL(d3dcompiler_34)
  256. WINE_CONFIG_DLL(d3dcompiler_35)
  257. diff --git a/dlls/d3d9-nine/Makefile.in b/dlls/d3d9-nine/Makefile.in
  258. new file mode 100644
  259. index 0000000000..c6df8d7dbe
  260. --- /dev/null
  261. +++ b/dlls/d3d9-nine/Makefile.in
  262. @@ -0,0 +1,15 @@
  263. +MODULE = d3d9-nine.dll
  264. +IMPORTS = dxguid uuid advapi32 gdi32 user32
  265. +EXTRAINCL = $(X_CFLAGS) $(D3D9NINE_HEADERS_CFLAGS)
  266. +EXTRALIBS = $(D3D9NINE_LIBS)
  267. +
  268. +C_SRCS = \
  269. + d3d9_main.c \
  270. + d3dadapter9.c \
  271. + device_wrap.c \
  272. + present.c \
  273. + dri3.c \
  274. + wndproc.c \
  275. + shader_validator.c
  276. +
  277. +RC_SRCS = version.rc
  278. diff --git a/dlls/d3d9-nine/d3d9-nine.spec b/dlls/d3d9-nine/d3d9-nine.spec
  279. new file mode 100644
  280. index 0000000000..a33cba51e7
  281. --- /dev/null
  282. +++ b/dlls/d3d9-nine/d3d9-nine.spec
  283. @@ -0,0 +1,14 @@
  284. +@ stdcall Direct3DShaderValidatorCreate9()
  285. +@ stub PSGPError
  286. +@ stub PSGPSampleTexture
  287. +@ stdcall D3DPERF_BeginEvent(long wstr)
  288. +@ stdcall D3DPERF_EndEvent()
  289. +@ stdcall D3DPERF_GetStatus()
  290. +@ stdcall D3DPERF_QueryRepeatFrame()
  291. +@ stdcall D3DPERF_SetMarker(long wstr)
  292. +@ stdcall D3DPERF_SetOptions(long)
  293. +@ stdcall D3DPERF_SetRegion(long wstr)
  294. +@ stub DebugSetLevel
  295. +@ stdcall DebugSetMute()
  296. +@ stdcall Direct3DCreate9(long)
  297. +@ stdcall Direct3DCreate9Ex(long ptr)
  298. diff --git a/dlls/d3d9-nine/d3d9_main.c b/dlls/d3d9-nine/d3d9_main.c
  299. new file mode 100644
  300. index 0000000000..d1efdf4a71
  301. --- /dev/null
  302. +++ b/dlls/d3d9-nine/d3d9_main.c
  303. @@ -0,0 +1,173 @@
  304. +/*
  305. + * Direct3D 9
  306. + *
  307. + * Copyright 2002-2003 Jason Edmeades
  308. + * Copyright 2002-2003 Raphael Junqueira
  309. + * Copyright 2005 Oliver Stieber
  310. + * Copyright 2015 Patrick Rudolph
  311. + *
  312. + * This library is free software; you can redistribute it and/or
  313. + * modify it under the terms of the GNU Lesser General Public
  314. + * License as published by the Free Software Foundation; either
  315. + * version 2.1 of the License, or (at your option) any later version.
  316. + *
  317. + * This library is distributed in the hope that it will be useful,
  318. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  319. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  320. + * Lesser General Public License for more details.
  321. + *
  322. + * You should have received a copy of the GNU Lesser General Public
  323. + * License along with this library; if not, write to the Free Software
  324. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  325. + *
  326. + */
  327. +
  328. +#include "config.h"
  329. +#include "wine/debug.h"
  330. +
  331. +#include <fcntl.h>
  332. +#include <d3d9.h>
  333. +
  334. +#include "d3dadapter9.h"
  335. +#include "wndproc.h"
  336. +#include "shader_validator.h"
  337. +
  338. +WINE_DEFAULT_DEBUG_CHANNEL(d3d9nine);
  339. +
  340. +static int D3DPERF_event_level = 0;
  341. +static Display *gdi_display;
  342. +
  343. +void WINAPI DebugSetMute(void)
  344. +{
  345. + /* nothing to do */
  346. +}
  347. +
  348. +IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9(UINT sdk_version)
  349. +{
  350. + IDirect3D9 *native;
  351. + TRACE("sdk_version %#x.\n", sdk_version);
  352. +
  353. + if (SUCCEEDED(d3dadapter9_new(gdi_display, FALSE, (IDirect3D9Ex **)&native)))
  354. + return native;
  355. +
  356. + return NULL;
  357. +}
  358. +
  359. +HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9Ex **d3d9ex)
  360. +{
  361. + TRACE("sdk_version %#x, d3d9ex %p.\n", sdk_version, d3d9ex);
  362. +
  363. + return d3dadapter9_new(gdi_display, TRUE, d3d9ex);
  364. +}
  365. +
  366. +/*******************************************************************
  367. + * Direct3DShaderValidatorCreate9 (D3D9.@)
  368. + *
  369. + * No documentation available for this function.
  370. + * SDK only says it is internal and shouldn't be used.
  371. + */
  372. +
  373. +void* WINAPI Direct3DShaderValidatorCreate9(void)
  374. +{
  375. + IDirect3DShaderValidator9Impl* object =
  376. + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  377. + sizeof(IDirect3DShaderValidator9Impl));
  378. +
  379. + object->lpVtbl = &IDirect3DShaderValidator9Vtbl;
  380. + object->ref = 1;
  381. +
  382. + FIXME("Returning interface %p\n", object);
  383. + return (void*) object;
  384. +}
  385. +
  386. +/*******************************************************************
  387. + * DllMain
  388. + */
  389. +BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
  390. +{
  391. + switch (reason)
  392. + {
  393. + case DLL_PROCESS_ATTACH:
  394. + if (!(gdi_display = XOpenDisplay( NULL )))
  395. + {
  396. + ERR("Failed to open display\n");
  397. + return FALSE;
  398. + }
  399. +
  400. + fcntl( ConnectionNumber(gdi_display), F_SETFD, 1 ); /* set close on exec flag */
  401. +
  402. + nine_dll_init(inst);
  403. + break;
  404. + case DLL_PROCESS_DETACH:
  405. + if (!reserved)
  406. + return nine_dll_destroy(inst);
  407. + break;
  408. + }
  409. +
  410. + return TRUE;
  411. +}
  412. +
  413. +/***********************************************************************
  414. + * D3DPERF_BeginEvent (D3D9.@)
  415. + */
  416. +int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, const WCHAR *name)
  417. +{
  418. + TRACE("color 0x%08x, name %s.\n", color, debugstr_w(name));
  419. +
  420. + return D3DPERF_event_level++;
  421. +}
  422. +
  423. +/***********************************************************************
  424. + * D3DPERF_EndEvent (D3D9.@)
  425. + */
  426. +int WINAPI D3DPERF_EndEvent(void)
  427. +{
  428. + TRACE("(void) : stub\n");
  429. +
  430. + return --D3DPERF_event_level;
  431. +}
  432. +
  433. +/***********************************************************************
  434. + * D3DPERF_GetStatus (D3D9.@)
  435. + */
  436. +DWORD WINAPI D3DPERF_GetStatus(void)
  437. +{
  438. + FIXME("(void) : stub\n");
  439. +
  440. + return 0;
  441. +}
  442. +
  443. +/***********************************************************************
  444. + * D3DPERF_SetOptions (D3D9.@)
  445. + *
  446. + */
  447. +void WINAPI D3DPERF_SetOptions(DWORD options)
  448. +{
  449. + FIXME("(%#x) : stub\n", options);
  450. +}
  451. +
  452. +/***********************************************************************
  453. + * D3DPERF_QueryRepeatFrame (D3D9.@)
  454. + */
  455. +BOOL WINAPI D3DPERF_QueryRepeatFrame(void)
  456. +{
  457. + FIXME("(void) : stub\n");
  458. +
  459. + return FALSE;
  460. +}
  461. +
  462. +/***********************************************************************
  463. + * D3DPERF_SetMarker (D3D9.@)
  464. + */
  465. +void WINAPI D3DPERF_SetMarker(D3DCOLOR color, const WCHAR *name)
  466. +{
  467. + FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
  468. +}
  469. +
  470. +/***********************************************************************
  471. + * D3DPERF_SetRegion (D3D9.@)
  472. + */
  473. +void WINAPI D3DPERF_SetRegion(D3DCOLOR color, const WCHAR *name)
  474. +{
  475. + FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
  476. +}
  477. diff --git a/dlls/d3d9-nine/d3dadapter9.c b/dlls/d3d9-nine/d3dadapter9.c
  478. new file mode 100644
  479. index 0000000000..188eebf763
  480. --- /dev/null
  481. +++ b/dlls/d3d9-nine/d3dadapter9.c
  482. @@ -0,0 +1,898 @@
  483. +/*
  484. + * Wine IDirect3D9 interface using ID3DAdapter9
  485. + *
  486. + * Copyright 2013 Joakim Sindholt
  487. + * Christoph Bumiller
  488. + * Copyright 2014 David Heidelberger
  489. + * Copyright 2014-2015 Axel Davy
  490. + * Copyright 2015 Nick Sarnie
  491. + * Patrick Rudolph
  492. + *
  493. + * This library is free software; you can redistribute it and/or
  494. + * modify it under the terms of the GNU Lesser General Public
  495. + * License as published by the Free Software Foundation; either
  496. + * version 2.1 of the License, or (at your option) any later version.
  497. + *
  498. + * This library is distributed in the hope that it will be useful,
  499. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  500. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  501. + * Lesser General Public License for more details.
  502. + *
  503. + * You should have received a copy of the GNU Lesser General Public
  504. + * License along with this library; if not, write to the Free Software
  505. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  506. + */
  507. +
  508. +#include "config.h"
  509. +#include "wine/debug.h"
  510. +
  511. +WINE_DEFAULT_DEBUG_CHANNEL(d3d9nine);
  512. +
  513. +#include <d3dadapter/d3dadapter9.h>
  514. +#include "present.h"
  515. +#include "device_wrap.h"
  516. +
  517. +/* this represents a snapshot taken at the moment of creation */
  518. +struct output
  519. +{
  520. + D3DDISPLAYROTATION rotation; /* current rotation */
  521. + D3DDISPLAYMODEEX *modes;
  522. + unsigned nmodes;
  523. + unsigned nmodesalloc;
  524. + unsigned current; /* current mode num */
  525. +
  526. + HMONITOR monitor;
  527. +};
  528. +
  529. +struct adapter_group
  530. +{
  531. + struct output *outputs;
  532. + unsigned noutputs;
  533. + unsigned noutputsalloc;
  534. +
  535. + /* override driver provided DeviceName with this to homogenize device names
  536. + * with wine */
  537. + WCHAR devname[32];
  538. +
  539. + /* driver stuff */
  540. + ID3DAdapter9 *adapter;
  541. +};
  542. +
  543. +struct adapter_map
  544. +{
  545. + unsigned group;
  546. + unsigned master;
  547. +};
  548. +
  549. +struct d3dadapter9
  550. +{
  551. + /* COM vtable */
  552. + void *vtable;
  553. + /* IUnknown reference count */
  554. + LONG refs;
  555. +
  556. + /* adapter groups and mappings */
  557. + struct adapter_group *groups;
  558. + struct adapter_map *map;
  559. + unsigned nadapters;
  560. + unsigned ngroups;
  561. + unsigned ngroupsalloc;
  562. +
  563. + /* true if it implements IDirect3D9Ex */
  564. + boolean ex;
  565. + Display *gdi_display;
  566. +};
  567. +
  568. +/* convenience wrapper for calls into ID3D9Adapter */
  569. +#define ADAPTER_GROUP \
  570. + This->groups[This->map[Adapter].group]
  571. +
  572. +#define ADAPTER_PROC(name, ...) \
  573. + ID3DAdapter9_##name(ADAPTER_GROUP.adapter, ## __VA_ARGS__)
  574. +
  575. +#define ADAPTER_OUTPUT \
  576. + ADAPTER_GROUP.outputs[Adapter-This->map[Adapter].master]
  577. +
  578. +static HRESULT WINAPI d3dadapter9_CheckDeviceFormat(struct d3dadapter9 *This,
  579. + UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
  580. + DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat);
  581. +
  582. +static ULONG WINAPI d3dadapter9_AddRef(struct d3dadapter9 *This)
  583. +{
  584. + ULONG refs = InterlockedIncrement(&This->refs);
  585. + TRACE("%p increasing refcount to %u.\n", This, refs);
  586. + return refs;
  587. +}
  588. +
  589. +static ULONG WINAPI d3dadapter9_Release(struct d3dadapter9 *This)
  590. +{
  591. + ULONG refs = InterlockedDecrement(&This->refs);
  592. + TRACE("%p decreasing refcount to %u.\n", This, refs);
  593. + if (refs == 0)
  594. + {
  595. + /* dtor */
  596. + if (This->map)
  597. + {
  598. + HeapFree(GetProcessHeap(), 0, This->map);
  599. + }
  600. +
  601. + if (This->groups)
  602. + {
  603. + int i, j;
  604. + for (i = 0; i < This->ngroups; ++i)
  605. + {
  606. + if (This->groups[i].outputs)
  607. + {
  608. + for (j = 0; j < This->groups[i].noutputs; ++j)
  609. + {
  610. + if (This->groups[i].outputs[j].modes)
  611. + {
  612. + HeapFree(GetProcessHeap(), 0,
  613. + This->groups[i].outputs[j].modes);
  614. + }
  615. + }
  616. + HeapFree(GetProcessHeap(), 0, This->groups[i].outputs);
  617. + }
  618. +
  619. + if (This->groups[i].adapter)
  620. + ID3DAdapter9_Release(This->groups[i].adapter);
  621. + }
  622. + HeapFree(GetProcessHeap(), 0, This->groups);
  623. + }
  624. +
  625. + HeapFree(GetProcessHeap(), 0, This);
  626. + }
  627. + return refs;
  628. +}
  629. +
  630. +static HRESULT WINAPI d3dadapter9_QueryInterface(struct d3dadapter9 *This,
  631. + REFIID riid, void **ppvObject)
  632. +{
  633. + if (!ppvObject)
  634. + return E_POINTER;
  635. +
  636. + if ((IsEqualGUID(&IID_IDirect3D9Ex, riid) && This->ex) ||
  637. + IsEqualGUID(&IID_IDirect3D9, riid) ||
  638. + IsEqualGUID(&IID_IUnknown, riid))
  639. + {
  640. + *ppvObject = This;
  641. + d3dadapter9_AddRef(This);
  642. + return S_OK;
  643. + }
  644. +
  645. + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
  646. + *ppvObject = NULL;
  647. +
  648. + return E_NOINTERFACE;
  649. +}
  650. +
  651. +static HRESULT WINAPI d3dadapter9_RegisterSoftwareDevice(struct d3dadapter9 *This,
  652. + void *pInitializeFunction)
  653. +{
  654. + FIXME("(%p, %p), stub!\n", This, pInitializeFunction);
  655. + return D3DERR_INVALIDCALL;
  656. +}
  657. +
  658. +static UINT WINAPI d3dadapter9_GetAdapterCount(struct d3dadapter9 *This)
  659. +{
  660. + return This->nadapters;
  661. +}
  662. +
  663. +static HRESULT WINAPI d3dadapter9_GetAdapterIdentifier(struct d3dadapter9 *This,
  664. + UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9 *pIdentifier)
  665. +{
  666. + HRESULT hr;
  667. + HKEY regkey;
  668. +
  669. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  670. + return D3DERR_INVALIDCALL;
  671. +
  672. + hr = ADAPTER_PROC(GetAdapterIdentifier, Flags, pIdentifier);
  673. + if (SUCCEEDED(hr))
  674. + {
  675. + /* Override the driver provided DeviceName with what Wine provided */
  676. + ZeroMemory(pIdentifier->DeviceName, sizeof(pIdentifier->DeviceName));
  677. + if (!WideCharToMultiByte(CP_ACP, 0, ADAPTER_GROUP.devname, -1,
  678. + pIdentifier->DeviceName, sizeof(pIdentifier->DeviceName), NULL, NULL))
  679. + return D3DERR_INVALIDCALL;
  680. +
  681. + TRACE("DeviceName overriden: %s\n", pIdentifier->DeviceName);
  682. +
  683. + /* Override PCI IDs when wined3d registry keys are set */
  684. + if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Direct3DNine", &regkey))
  685. + {
  686. + DWORD type, data;
  687. + DWORD size = sizeof(DWORD);
  688. +
  689. + if (!RegQueryValueExA(regkey, "VideoPciDeviceID", 0, &type, (BYTE *)&data, &size) &&
  690. + (type == REG_DWORD) && (size == sizeof(DWORD)))
  691. + pIdentifier->DeviceId = data;
  692. + if (size != sizeof(DWORD))
  693. + {
  694. + ERR("VideoPciDeviceID is not a DWORD\n");
  695. + size = sizeof(DWORD);
  696. + }
  697. + if (!RegQueryValueExA(regkey, "VideoPciVendorID", 0, &type, (BYTE *)&data, &size) &&
  698. + (type == REG_DWORD) && (size == sizeof(DWORD)))
  699. + pIdentifier->VendorId = data;
  700. + if (size != sizeof(DWORD))
  701. + ERR("VideoPciVendorID is not a DWORD\n");
  702. + RegCloseKey(regkey);
  703. +
  704. + TRACE("DeviceId:VendorId overridden: %04X:%04X\n", pIdentifier->DeviceId, pIdentifier->VendorId);
  705. + }
  706. + }
  707. + return hr;
  708. +}
  709. +
  710. +static UINT WINAPI d3dadapter9_GetAdapterModeCount(struct d3dadapter9 *This,
  711. + UINT Adapter, D3DFORMAT Format)
  712. +{
  713. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  714. + return D3DERR_INVALIDCALL;
  715. +
  716. + if (FAILED(d3dadapter9_CheckDeviceFormat(This, Adapter, D3DDEVTYPE_HAL,
  717. + Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, Format)))
  718. + {
  719. + WARN("DeviceFormat not available.\n");
  720. + return 0;
  721. + }
  722. +
  723. + TRACE("%u modes.\n", ADAPTER_OUTPUT.nmodes);
  724. + return ADAPTER_OUTPUT.nmodes;
  725. +}
  726. +
  727. +static HRESULT WINAPI d3dadapter9_EnumAdapterModes(struct d3dadapter9 *This,
  728. + UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE *pMode)
  729. +{
  730. + HRESULT hr;
  731. +
  732. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  733. + return D3DERR_INVALIDCALL;
  734. +
  735. + hr = d3dadapter9_CheckDeviceFormat(This, Adapter, D3DDEVTYPE_HAL,
  736. + Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, Format);
  737. +
  738. + if (FAILED(hr))
  739. + {
  740. + TRACE("DeviceFormat not available.\n");
  741. + return hr;
  742. + }
  743. +
  744. + if (Mode >= ADAPTER_OUTPUT.nmodes)
  745. + {
  746. + WARN("Mode %u does not exist.\n", Mode);
  747. + return D3DERR_INVALIDCALL;
  748. + }
  749. +
  750. + pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
  751. + pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
  752. + pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
  753. + pMode->Format = Format;
  754. +
  755. + return D3D_OK;
  756. +}
  757. +
  758. +static HRESULT WINAPI d3dadapter9_GetAdapterDisplayMode(struct d3dadapter9 *This,
  759. + UINT Adapter, D3DDISPLAYMODE *pMode)
  760. +{
  761. + UINT Mode;
  762. +
  763. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  764. + return D3DERR_INVALIDCALL;
  765. +
  766. + Mode = ADAPTER_OUTPUT.current;
  767. + pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
  768. + pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
  769. + pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
  770. + pMode->Format = ADAPTER_OUTPUT.modes[Mode].Format;
  771. +
  772. + return D3D_OK;
  773. +}
  774. +
  775. +static HRESULT WINAPI d3dadapter9_CheckDeviceType(struct d3dadapter9 *This,
  776. + UINT Adapter, D3DDEVTYPE DevType, D3DFORMAT AdapterFormat,
  777. + D3DFORMAT BackBufferFormat, BOOL bWindowed)
  778. +{
  779. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  780. + return D3DERR_INVALIDCALL;
  781. +
  782. + return ADAPTER_PROC(CheckDeviceType,
  783. + DevType, AdapterFormat, BackBufferFormat, bWindowed);
  784. +}
  785. +
  786. +static HRESULT WINAPI d3dadapter9_CheckDeviceFormat(struct d3dadapter9 *This,
  787. + UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
  788. + DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat)
  789. +{
  790. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  791. + return D3DERR_INVALIDCALL;
  792. +
  793. + return ADAPTER_PROC(CheckDeviceFormat,
  794. + DeviceType, AdapterFormat, Usage, RType, CheckFormat);
  795. +}
  796. +
  797. +static HRESULT WINAPI d3dadapter9_CheckDeviceMultiSampleType(struct d3dadapter9 *This,
  798. + UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
  799. + BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
  800. +{
  801. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  802. + return D3DERR_INVALIDCALL;
  803. +
  804. + return ADAPTER_PROC(CheckDeviceMultiSampleType, DeviceType, SurfaceFormat,
  805. + Windowed, MultiSampleType, pQualityLevels);
  806. +}
  807. +
  808. +static HRESULT WINAPI d3dadapter9_CheckDepthStencilMatch(struct d3dadapter9 *This,
  809. + UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
  810. + D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat)
  811. +{
  812. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  813. + return D3DERR_INVALIDCALL;
  814. +
  815. + return ADAPTER_PROC(CheckDepthStencilMatch, DeviceType, AdapterFormat,
  816. + RenderTargetFormat, DepthStencilFormat);
  817. +}
  818. +
  819. +static HRESULT WINAPI d3dadapter9_CheckDeviceFormatConversion(struct d3dadapter9 *This,
  820. + UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat)
  821. +{
  822. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  823. + return D3DERR_INVALIDCALL;
  824. +
  825. + return ADAPTER_PROC(CheckDeviceFormatConversion,
  826. + DeviceType, SourceFormat, TargetFormat);
  827. +}
  828. +
  829. +static HRESULT WINAPI d3dadapter9_GetDeviceCaps(struct d3dadapter9 *This,
  830. + UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9 *pCaps)
  831. +{
  832. + HRESULT hr;
  833. +
  834. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  835. + return D3DERR_INVALIDCALL;
  836. +
  837. + hr = ADAPTER_PROC(GetDeviceCaps, DeviceType, pCaps);
  838. + if (FAILED(hr))
  839. + return hr;
  840. +
  841. + pCaps->MasterAdapterOrdinal = This->map[Adapter].master;
  842. + pCaps->AdapterOrdinalInGroup = Adapter-This->map[Adapter].master;
  843. + pCaps->NumberOfAdaptersInGroup = ADAPTER_GROUP.noutputs;
  844. +
  845. + return hr;
  846. +}
  847. +
  848. +static HMONITOR WINAPI d3dadapter9_GetAdapterMonitor(struct d3dadapter9 *This,
  849. + UINT Adapter)
  850. +{
  851. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  852. + return (HMONITOR)0;
  853. +
  854. + return (HMONITOR)ADAPTER_OUTPUT.monitor;
  855. +}
  856. +
  857. +static HRESULT WINAPI DECLSPEC_HOTPATCH d3dadapter9_CreateDeviceEx(struct d3dadapter9 *This,
  858. + UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
  859. + D3DPRESENT_PARAMETERS *pPresentationParameters,
  860. + D3DDISPLAYMODEEX *pFullscreenDisplayMode,
  861. + IDirect3DDevice9Ex **ppReturnedDeviceInterface);
  862. +
  863. +static HRESULT WINAPI DECLSPEC_HOTPATCH d3dadapter9_CreateDevice(struct d3dadapter9 *This,
  864. + UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
  865. + D3DPRESENT_PARAMETERS *pPresentationParameters,
  866. + IDirect3DDevice9 **ppReturnedDeviceInterface)
  867. +{
  868. + HRESULT hr;
  869. + hr = d3dadapter9_CreateDeviceEx(This, Adapter, DeviceType, hFocusWindow,
  870. + BehaviorFlags, pPresentationParameters, NULL,
  871. + (IDirect3DDevice9Ex **)ppReturnedDeviceInterface);
  872. + if (FAILED(hr))
  873. + return hr;
  874. +
  875. + return D3D_OK;
  876. +}
  877. +
  878. +static UINT WINAPI d3dadapter9_GetAdapterModeCountEx(struct d3dadapter9 *This,
  879. + UINT Adapter, const D3DDISPLAYMODEFILTER *pFilter)
  880. +{
  881. + FIXME("(%p, %u, %p), half stub!\n", This, Adapter, pFilter);
  882. + return d3dadapter9_GetAdapterModeCount(This, Adapter, pFilter->Format);
  883. +}
  884. +
  885. +static HRESULT WINAPI d3dadapter9_EnumAdapterModesEx(struct d3dadapter9 *This,
  886. + UINT Adapter, const D3DDISPLAYMODEFILTER *pFilter, UINT Mode,
  887. + D3DDISPLAYMODEEX *pMode)
  888. +{
  889. + HRESULT hr;
  890. +
  891. + FIXME("(%p, %u, %p, %u, %p), half stub!\n", This, Adapter, pFilter, Mode, pMode);
  892. +
  893. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  894. + return D3DERR_INVALIDCALL;
  895. +
  896. + hr = d3dadapter9_CheckDeviceFormat(This, Adapter, D3DDEVTYPE_HAL,
  897. + pFilter->Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, pFilter->Format);
  898. +
  899. + if (FAILED(hr))
  900. + {
  901. + TRACE("DeviceFormat not available.\n");
  902. + return hr;
  903. + }
  904. +
  905. + if (Mode >= ADAPTER_OUTPUT.nmodes)
  906. + {
  907. + WARN("Mode %u does not exist.\n", Mode);
  908. + return D3DERR_INVALIDCALL;
  909. + }
  910. +
  911. + pMode->Size = ADAPTER_OUTPUT.modes[Mode].Size;
  912. + pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
  913. + pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
  914. + pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
  915. + pMode->Format = ADAPTER_OUTPUT.modes[Mode].Format;
  916. + pMode->ScanLineOrdering = ADAPTER_OUTPUT.modes[Mode].ScanLineOrdering;
  917. +
  918. + return D3D_OK;
  919. +}
  920. +
  921. +static HRESULT WINAPI d3dadapter9_GetAdapterDisplayModeEx(struct d3dadapter9 *This,
  922. + UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation)
  923. +{
  924. + UINT Mode;
  925. +
  926. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  927. + return D3DERR_INVALIDCALL;
  928. +
  929. + if (pMode)
  930. + {
  931. + Mode = ADAPTER_OUTPUT.current;
  932. + pMode->Size = sizeof(D3DDISPLAYMODEEX);
  933. + pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
  934. + pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
  935. + pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
  936. + pMode->Format = ADAPTER_OUTPUT.modes[Mode].Format;
  937. + pMode->ScanLineOrdering = ADAPTER_OUTPUT.modes[Mode].ScanLineOrdering;
  938. + }
  939. + if (pRotation)
  940. + *pRotation = ADAPTER_OUTPUT.rotation;
  941. +
  942. + return D3D_OK;
  943. +}
  944. +
  945. +static HRESULT WINAPI DECLSPEC_HOTPATCH d3dadapter9_CreateDeviceEx(struct d3dadapter9 *This,
  946. + UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
  947. + D3DPRESENT_PARAMETERS *pPresentationParameters,
  948. + D3DDISPLAYMODEEX *pFullscreenDisplayMode,
  949. + IDirect3DDevice9Ex **ppReturnedDeviceInterface)
  950. +{
  951. + ID3DPresentGroup *present;
  952. + HRESULT hr;
  953. +
  954. + if (Adapter >= d3dadapter9_GetAdapterCount(This))
  955. + return D3DERR_INVALIDCALL;
  956. +
  957. + {
  958. + struct adapter_group *group = &ADAPTER_GROUP;
  959. + unsigned nparams, ordinal;
  960. +
  961. + if (BehaviorFlags & D3DCREATE_ADAPTERGROUP_DEVICE)
  962. + {
  963. + nparams = group->noutputs;
  964. + ordinal = 0;
  965. + }
  966. + else
  967. + {
  968. + nparams = 1;
  969. + ordinal = Adapter - This->map[Adapter].master;
  970. + }
  971. + hr = present_create_present_group(This->gdi_display, group->devname, ordinal,
  972. + hFocusWindow, pPresentationParameters, nparams, &present, This->ex,
  973. + BehaviorFlags);
  974. + }
  975. +
  976. + if (FAILED(hr))
  977. + {
  978. + WARN("Failed to create PresentGroup.\n");
  979. + return hr;
  980. + }
  981. +
  982. + if (This->ex)
  983. + {
  984. + hr = ADAPTER_PROC(CreateDeviceEx, Adapter, DeviceType, hFocusWindow,
  985. + BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode,
  986. + (IDirect3D9Ex *)This, present, ppReturnedDeviceInterface);
  987. + }
  988. + else
  989. + {
  990. + /* CreateDevice on non-ex */
  991. + hr = ADAPTER_PROC(CreateDevice, Adapter, DeviceType, hFocusWindow,
  992. + BehaviorFlags, pPresentationParameters, (IDirect3D9 *)This, present,
  993. + (IDirect3DDevice9 **)ppReturnedDeviceInterface);
  994. + }
  995. + if (FAILED(hr))
  996. + {
  997. + WARN("ADAPTER_PROC failed.\n");
  998. + ID3DPresentGroup_Release(present);
  999. + return hr;
  1000. + }
  1001. +
  1002. + /* Nine returns different vtables for Ex, non Ex and
  1003. + * if you use the multithread flag or not. This prevents
  1004. + * things like Steam overlay to work, in addition to the problem
  1005. + * that functions nine side are not recognized by wine as
  1006. + * hotpatch-able. If possible, we use our vtable wrapper,
  1007. + * which solves the problem described above. */
  1008. + if (enable_device_vtable_wrapper())
  1009. + (*ppReturnedDeviceInterface)->lpVtbl = get_device_vtable();
  1010. + return hr;
  1011. +}
  1012. +
  1013. +static HRESULT WINAPI d3dadapter9_GetAdapterLUID(struct d3dadapter9 *This,
  1014. + UINT Adapter, LUID *pLUID)
  1015. +{
  1016. + FIXME("(%p, %u, %p), stub!\n", This, Adapter, pLUID);
  1017. + return D3DERR_INVALIDCALL;
  1018. +}
  1019. +
  1020. +static struct adapter_group *add_group(struct d3dadapter9 *This)
  1021. +{
  1022. + if (This->ngroups >= This->ngroupsalloc)
  1023. + {
  1024. + void *r;
  1025. +
  1026. + if (This->ngroupsalloc == 0)
  1027. + {
  1028. + This->ngroupsalloc = 2;
  1029. + r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  1030. + This->ngroupsalloc*sizeof(struct adapter_group));
  1031. + }
  1032. + else
  1033. + {
  1034. + This->ngroupsalloc <<= 1;
  1035. + r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->groups,
  1036. + This->ngroupsalloc*sizeof(struct adapter_group));
  1037. + }
  1038. +
  1039. + if (!r)
  1040. + return NULL;
  1041. + This->groups = r;
  1042. + }
  1043. +
  1044. + return &This->groups[This->ngroups++];
  1045. +}
  1046. +
  1047. +static void remove_group(struct d3dadapter9 *This)
  1048. +{
  1049. + struct adapter_group *group = &This->groups[This->ngroups-1];
  1050. + int i;
  1051. +
  1052. + for (i = 0; i < group->noutputs; ++i)
  1053. + {
  1054. + HeapFree(GetProcessHeap(), 0, group->outputs[i].modes);
  1055. + }
  1056. + HeapFree(GetProcessHeap(), 0, group->outputs);
  1057. +
  1058. + ZeroMemory(group, sizeof(struct adapter_group));
  1059. + This->ngroups--;
  1060. +}
  1061. +
  1062. +static struct output *add_output(struct d3dadapter9 *This)
  1063. +{
  1064. + struct adapter_group *group = &This->groups[This->ngroups-1];
  1065. +
  1066. + if (group->noutputs >= group->noutputsalloc)
  1067. + {
  1068. + void *r;
  1069. +
  1070. + if (group->noutputsalloc == 0)
  1071. + {
  1072. + group->noutputsalloc = 2;
  1073. + r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  1074. + group->noutputsalloc*sizeof(struct output));
  1075. + }
  1076. + else
  1077. + {
  1078. + group->noutputsalloc <<= 1;
  1079. + r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, group->outputs,
  1080. + group->noutputsalloc*sizeof(struct output));
  1081. + }
  1082. +
  1083. + if (!r)
  1084. + return NULL;
  1085. + group->outputs = r;
  1086. + }
  1087. +
  1088. + return &group->outputs[group->noutputs++];
  1089. +}
  1090. +
  1091. +static void remove_output(struct d3dadapter9 *This)
  1092. +{
  1093. + struct adapter_group *group = &This->groups[This->ngroups-1];
  1094. + struct output *out = &group->outputs[group->noutputs-1];
  1095. +
  1096. + HeapFree(GetProcessHeap(), 0, out->modes);
  1097. +
  1098. + ZeroMemory(out, sizeof(struct output));
  1099. + group->noutputs--;
  1100. +}
  1101. +
  1102. +static D3DDISPLAYMODEEX *add_mode(struct d3dadapter9 *This)
  1103. +{
  1104. + struct adapter_group *group = &This->groups[This->ngroups-1];
  1105. + struct output *out = &group->outputs[group->noutputs-1];
  1106. +
  1107. + if (out->nmodes >= out->nmodesalloc)
  1108. + {
  1109. + void *r;
  1110. +
  1111. + if (out->nmodesalloc == 0)
  1112. + {
  1113. + out->nmodesalloc = 8;
  1114. + r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  1115. + out->nmodesalloc*sizeof(struct D3DDISPLAYMODEEX));
  1116. + }
  1117. + else
  1118. + {
  1119. + out->nmodesalloc <<= 1;
  1120. + r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, out->modes,
  1121. + out->nmodesalloc*sizeof(struct D3DDISPLAYMODEEX));
  1122. + }
  1123. +
  1124. + if (!r)
  1125. + return NULL;
  1126. + out->modes = r;
  1127. + }
  1128. +
  1129. + return &out->modes[out->nmodes++];
  1130. +}
  1131. +
  1132. +static void remove_mode(struct d3dadapter9 *This)
  1133. +{
  1134. + struct adapter_group *group = &This->groups[This->ngroups-1];
  1135. + struct output *out = &group->outputs[group->noutputs-1];
  1136. + out->nmodes--;
  1137. +}
  1138. +
  1139. +static HRESULT fill_groups(struct d3dadapter9 *This)
  1140. +{
  1141. + DISPLAY_DEVICEW dd;
  1142. + DEVMODEW dm;
  1143. + POINT pt;
  1144. + HDC hdc;
  1145. + HRESULT hr;
  1146. + int i, j, k;
  1147. +
  1148. + WCHAR wdisp[] = {'D','I','S','P','L','A','Y',0};
  1149. +
  1150. + ZeroMemory(&dd, sizeof(dd));
  1151. + ZeroMemory(&dm, sizeof(dm));
  1152. + dd.cb = sizeof(dd);
  1153. + dm.dmSize = sizeof(dm);
  1154. +
  1155. + for (i = 0; EnumDisplayDevicesW(NULL, i, &dd, 0); ++i)
  1156. + {
  1157. + struct adapter_group *group = add_group(This);
  1158. + if (!group)
  1159. + {
  1160. + ERR("Out of memory.\n");
  1161. + return E_OUTOFMEMORY;
  1162. + }
  1163. +
  1164. + hdc = CreateDCW(wdisp, dd.DeviceName, NULL, NULL);
  1165. + if (!hdc)
  1166. + {
  1167. + remove_group(This);
  1168. + WARN("Unable to create DC for display %d.\n", i);
  1169. + goto end_group;
  1170. + }
  1171. +
  1172. + hr = present_create_adapter9(This->gdi_display, hdc, &group->adapter);
  1173. + DeleteDC(hdc);
  1174. + if (FAILED(hr))
  1175. + {
  1176. + remove_group(This);
  1177. + goto end_group;
  1178. + }
  1179. +
  1180. + CopyMemory(group->devname, dd.DeviceName, sizeof(group->devname));
  1181. + for (j = 0; EnumDisplayDevicesW(group->devname, j, &dd, 0); ++j)
  1182. + {
  1183. + struct output *out = add_output(This);
  1184. + boolean orient = FALSE, monit = FALSE;
  1185. + if (!out)
  1186. + {
  1187. + ERR("Out of memory.\n");
  1188. + return E_OUTOFMEMORY;
  1189. + }
  1190. +
  1191. + for (k = 0; EnumDisplaySettingsExW(dd.DeviceName, k, &dm, 0); ++k)
  1192. + {
  1193. + D3DDISPLAYMODEEX *mode = add_mode(This);
  1194. + if (!out)
  1195. + {
  1196. + ERR("Out of memory.\n");
  1197. + return E_OUTOFMEMORY;
  1198. + }
  1199. +
  1200. + mode->Size = sizeof(D3DDISPLAYMODEEX);
  1201. + mode->Width = dm.dmPelsWidth;
  1202. + mode->Height = dm.dmPelsHeight;
  1203. + mode->RefreshRate = dm.dmDisplayFrequency;
  1204. + mode->ScanLineOrdering =
  1205. + (dm.dmDisplayFlags & DM_INTERLACED) ?
  1206. + D3DSCANLINEORDERING_INTERLACED :
  1207. + D3DSCANLINEORDERING_PROGRESSIVE;
  1208. +
  1209. + switch (dm.dmBitsPerPel)
  1210. + {
  1211. + case 32: mode->Format = D3DFMT_X8R8G8B8; break;
  1212. + case 24: mode->Format = D3DFMT_R8G8B8; break;
  1213. + case 16: mode->Format = D3DFMT_R5G6B5; break;
  1214. + case 8:
  1215. + remove_mode(This);
  1216. + goto end_mode;
  1217. +
  1218. + default:
  1219. + remove_mode(This);
  1220. + WARN("Unknown format (%u bpp) in display %d, monitor "
  1221. + "%d, mode %d.\n", dm.dmBitsPerPel, i, j, k);
  1222. + goto end_mode;
  1223. + }
  1224. +
  1225. + if (!orient)
  1226. + {
  1227. + switch (dm.dmDisplayOrientation)
  1228. + {
  1229. + case DMDO_DEFAULT:
  1230. + out->rotation = D3DDISPLAYROTATION_IDENTITY;
  1231. + break;
  1232. +
  1233. + case DMDO_90:
  1234. + out->rotation = D3DDISPLAYROTATION_90;
  1235. + break;
  1236. +
  1237. + case DMDO_180:
  1238. + out->rotation = D3DDISPLAYROTATION_180;
  1239. + break;
  1240. +
  1241. + case DMDO_270:
  1242. + out->rotation = D3DDISPLAYROTATION_270;
  1243. + break;
  1244. +
  1245. + default:
  1246. + remove_output(This);
  1247. + WARN("Unknown display rotation in display %d, "
  1248. + "monitor %d\n", i, j);
  1249. + goto end_output;
  1250. + }
  1251. + orient = TRUE;
  1252. + }
  1253. +
  1254. + if (!monit)
  1255. + {
  1256. + pt.x = dm.dmPosition.x;
  1257. + pt.y = dm.dmPosition.y;
  1258. + out->monitor = MonitorFromPoint(pt, 0);
  1259. + if (!out->monitor)
  1260. + {
  1261. + remove_output(This);
  1262. + WARN("Unable to get monitor handle for display %d, "
  1263. + "monitor %d.\n", i, j);
  1264. + goto end_output;
  1265. + }
  1266. + monit = TRUE;
  1267. + }
  1268. +
  1269. +end_mode:
  1270. + ZeroMemory(&dm, sizeof(dm));
  1271. + dm.dmSize = sizeof(dm);
  1272. + }
  1273. +
  1274. +end_output:
  1275. + ZeroMemory(&dd, sizeof(dd));
  1276. + dd.cb = sizeof(dd);
  1277. + }
  1278. +
  1279. +end_group:
  1280. + ZeroMemory(&dd, sizeof(dd));
  1281. + dd.cb = sizeof(dd);
  1282. + }
  1283. +
  1284. + return D3D_OK;
  1285. +}
  1286. +
  1287. +static IDirect3D9ExVtbl d3dadapter9_vtable = {
  1288. + (void *)d3dadapter9_QueryInterface,
  1289. + (void *)d3dadapter9_AddRef,
  1290. + (void *)d3dadapter9_Release,
  1291. + (void *)d3dadapter9_RegisterSoftwareDevice,
  1292. + (void *)d3dadapter9_GetAdapterCount,
  1293. + (void *)d3dadapter9_GetAdapterIdentifier,
  1294. + (void *)d3dadapter9_GetAdapterModeCount,
  1295. + (void *)d3dadapter9_EnumAdapterModes,
  1296. + (void *)d3dadapter9_GetAdapterDisplayMode,
  1297. + (void *)d3dadapter9_CheckDeviceType,
  1298. + (void *)d3dadapter9_CheckDeviceFormat,
  1299. + (void *)d3dadapter9_CheckDeviceMultiSampleType,
  1300. + (void *)d3dadapter9_CheckDepthStencilMatch,
  1301. + (void *)d3dadapter9_CheckDeviceFormatConversion,
  1302. + (void *)d3dadapter9_GetDeviceCaps,
  1303. + (void *)d3dadapter9_GetAdapterMonitor,
  1304. + (void *)d3dadapter9_CreateDevice,
  1305. + (void *)d3dadapter9_GetAdapterModeCountEx,
  1306. + (void *)d3dadapter9_EnumAdapterModesEx,
  1307. + (void *)d3dadapter9_GetAdapterDisplayModeEx,
  1308. + (void *)d3dadapter9_CreateDeviceEx,
  1309. + (void *)d3dadapter9_GetAdapterLUID
  1310. +};
  1311. +
  1312. +HRESULT d3dadapter9_new(Display *gdi_display, boolean ex, IDirect3D9Ex **ppOut)
  1313. +{
  1314. + struct d3dadapter9 *This;
  1315. + HRESULT hr;
  1316. + unsigned i, j, k;
  1317. +
  1318. + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct d3dadapter9));
  1319. + if (!This)
  1320. + {
  1321. + ERR("Out of memory.\n");
  1322. + return E_OUTOFMEMORY;
  1323. + }
  1324. +
  1325. + This->vtable = &d3dadapter9_vtable;
  1326. + This->refs = 1;
  1327. + This->ex = ex;
  1328. + This->gdi_display = gdi_display;
  1329. +
  1330. + if (!present_has_d3dadapter(gdi_display))
  1331. + {
  1332. + ERR("Your display driver doesn't support native D3D9 adapters.\n");
  1333. + d3dadapter9_Release(This);
  1334. + return D3DERR_NOTAVAILABLE;
  1335. + }
  1336. +
  1337. + if (FAILED(hr = fill_groups(This)))
  1338. + {
  1339. + d3dadapter9_Release(This);
  1340. + return hr;
  1341. + }
  1342. +
  1343. + /* map absolute adapter IDs with internal adapters */
  1344. + for (i = 0; i < This->ngroups; ++i)
  1345. + {
  1346. + for (j = 0; j < This->groups[i].noutputs; ++j)
  1347. + {
  1348. + This->nadapters++;
  1349. + }
  1350. + }
  1351. + if (This->nadapters == 0)
  1352. + {
  1353. + ERR("No available native adapters in system.\n");
  1354. + d3dadapter9_Release(This);
  1355. + return D3DERR_NOTAVAILABLE;
  1356. + }
  1357. +
  1358. + This->map = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  1359. + This->nadapters * sizeof(struct adapter_map));
  1360. +
  1361. + if (!This->map)
  1362. + {
  1363. + d3dadapter9_Release(This);
  1364. + ERR("Out of memory.\n");
  1365. + return E_OUTOFMEMORY;
  1366. + }
  1367. + for (i = k = 0; i < This->ngroups; ++i)
  1368. + {
  1369. + for (j = 0; j < This->groups[i].noutputs; ++j, ++k)
  1370. + {
  1371. + This->map[k].master = k-j;
  1372. + This->map[k].group = i;
  1373. + }
  1374. + }
  1375. +
  1376. + *ppOut = (IDirect3D9Ex *)This;
  1377. + FIXME("\033[1;32m\nNative Direct3D 9 is active."
  1378. + "\nFor more information visit https://wiki.ixit.cz/d3d9\033[0m\n");
  1379. + return D3D_OK;
  1380. +}
  1381. diff --git a/dlls/d3d9-nine/d3dadapter9.h b/dlls/d3d9-nine/d3dadapter9.h
  1382. new file mode 100644
  1383. index 0000000000..ad54f67285
  1384. --- /dev/null
  1385. +++ b/dlls/d3d9-nine/d3dadapter9.h
  1386. @@ -0,0 +1,32 @@
  1387. +/*
  1388. + * D3DAdapter9 interface
  1389. + *
  1390. + * Copyright 2015 Patrick Rudolph
  1391. + *
  1392. + * This library is free software; you can redistribute it and/or
  1393. + * modify it under the terms of the GNU Lesser General Public
  1394. + * License as published by the Free Software Foundation; either
  1395. + * version 2.1 of the License, or (at your option) any later version.
  1396. + *
  1397. + * This library is distributed in the hope that it will be useful,
  1398. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1399. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1400. + * Lesser General Public License for more details.
  1401. + *
  1402. + * You should have received a copy of the GNU Lesser General Public
  1403. + * License along with this library; if not, write to the Free Software
  1404. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  1405. + */
  1406. +
  1407. +#ifndef __WINE_D3D9ADAPTER_H
  1408. +#define __WINE_D3D9ADAPTER_H
  1409. +
  1410. +#include <X11/Xlib.h>
  1411. +
  1412. +void d3dadapter9_init(HINSTANCE hinst);
  1413. +
  1414. +void d3dadapter9_destroy(HINSTANCE hinst);
  1415. +
  1416. +HRESULT d3dadapter9_new(Display *gdi_display, boolean ex, IDirect3D9Ex **ppOut);
  1417. +
  1418. +#endif /* __WINE_D3D9ADAPTER_H */
  1419. diff --git a/dlls/d3d9-nine/device_wrap.c b/dlls/d3d9-nine/device_wrap.c
  1420. new file mode 100644
  1421. index 0000000000..e662c6f89a
  1422. --- /dev/null
  1423. +++ b/dlls/d3d9-nine/device_wrap.c
  1424. @@ -0,0 +1,500 @@
  1425. +/*
  1426. + * Copyright 2016 Axel Davy
  1427. + *
  1428. + * This library is free software; you can redistribute it and/or
  1429. + * modify it under the terms of the GNU Lesser General Public
  1430. + * License as published by the Free Software Foundation; either
  1431. + * version 2.1 of the License, or (at your option) any later version.
  1432. + *
  1433. + * This library is distributed in the hope that it will be useful,
  1434. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1435. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1436. + * Lesser General Public License for more details.
  1437. + *
  1438. + * You should have received a copy of the GNU Lesser General Public
  1439. + * License along with this library; if not, write to the Free Software
  1440. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  1441. + */
  1442. +
  1443. +#include "config.h"
  1444. +#include "wine/port.h"
  1445. +#include "wine/debug.h"
  1446. +
  1447. +#include <d3d9.h>
  1448. +
  1449. +#include "device_wrap.h"
  1450. +
  1451. +struct IDirect3DDevice9Ex_Minor1
  1452. +{
  1453. + IDirect3DDevice9ExVtbl *lpVtbl;
  1454. + IDirect3DDevice9ExVtbl *lpVtbl_internal;
  1455. +};
  1456. +
  1457. +struct IDirect3DSwapChain9Ex_Minor1
  1458. +{
  1459. + IDirect3DSwapChain9ExVtbl *lpVtbl;
  1460. + IDirect3DSwapChain9ExVtbl *lpVtbl_internal;
  1461. +};
  1462. +
  1463. +typedef struct IDirect3DDevice9Ex_Minor1 IDirect3DDevice9Ex_Minor1;
  1464. +typedef struct IDirect3DSwapChain9Ex_Minor1 IDirect3DSwapChain9Ex_Minor1;
  1465. +
  1466. +#define SWAPCHAIN_WRAP0(ret, func) \
  1467. + ret WINAPI WineNineSwapChain9_ ## func(IDirect3DSwapChain9Ex *This) \
  1468. + { \
  1469. + return ((IDirect3DSwapChain9Ex_Minor1 *)This)->lpVtbl_internal->func(This); \
  1470. + }
  1471. +
  1472. +#define SWAPCHAIN_WRAP1(ret, func, type1) \
  1473. + ret WINAPI WineNineSwapChain9_ ## func(IDirect3DSwapChain9Ex *This, type1 arg1) \
  1474. + { \
  1475. + return ((IDirect3DSwapChain9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1); \
  1476. + }
  1477. +
  1478. +#define SWAPCHAIN_WRAP2(ret, func, type1, type2) \
  1479. + ret WINAPI WineNineSwapChain9_ ## func(IDirect3DSwapChain9Ex *This, type1 arg1, type2 arg2) \
  1480. + { \
  1481. + return ((IDirect3DSwapChain9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2); \
  1482. + }
  1483. +
  1484. +#define SWAPCHAIN_WRAP3(ret, func, type1, type2, type3) \
  1485. + ret WINAPI WineNineSwapChain9_ ## func(IDirect3DSwapChain9Ex *This, type1 arg1, type2 arg2, type3 arg3) \
  1486. + { \
  1487. + return ((IDirect3DSwapChain9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3); \
  1488. + }
  1489. +
  1490. +#define SWAPCHAIN_H_WRAP5(ret, func, type1, type2, type3, type4, type5) \
  1491. + ret WINAPI DECLSPEC_HOTPATCH WineNineSwapChain9_ ## func(IDirect3DSwapChain9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
  1492. + { \
  1493. + return ((IDirect3DSwapChain9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5); \
  1494. + }
  1495. +
  1496. +#define DEVICE_WRAP0(ret, func) \
  1497. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This) \
  1498. + { \
  1499. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This); \
  1500. + }
  1501. +
  1502. +#define DEVICE_WRAP1(ret, func, type1) \
  1503. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1) \
  1504. + { \
  1505. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1); \
  1506. + }
  1507. +
  1508. +#define DEVICE_WRAP2(ret, func, type1, type2) \
  1509. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2) \
  1510. + { \
  1511. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2); \
  1512. + }
  1513. +
  1514. +#define DEVICE_WRAP3(ret, func, type1, type2, type3) \
  1515. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3) \
  1516. + { \
  1517. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3); \
  1518. + }
  1519. +
  1520. +#define DEVICE_WRAP4(ret, func, type1, type2, type3, type4) \
  1521. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
  1522. + { \
  1523. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4); \
  1524. + }
  1525. +
  1526. +#define DEVICE_WRAP5(ret, func, type1, type2, type3, type4, type5) \
  1527. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
  1528. + { \
  1529. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5); \
  1530. + }
  1531. +
  1532. +#define DEVICE_WRAP6(ret, func, type1, type2, type3, type4, type5, type6) \
  1533. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
  1534. + { \
  1535. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5, arg6); \
  1536. + }
  1537. +
  1538. +#define DEVICE_WRAP7(ret, func, type1, type2, type3, type4, type5, type6, type7) \
  1539. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) \
  1540. + { \
  1541. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
  1542. + }
  1543. +
  1544. +#define DEVICE_WRAP8(ret, func, type1, type2, type3, type4, type5, type6, type7, type8) \
  1545. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) \
  1546. + { \
  1547. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
  1548. + }
  1549. +
  1550. +#define DEVICE_WRAP9(ret, func, type1, type2, type3, type4, type5, type6, type7, type8, type9) \
  1551. + ret WINAPI WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) \
  1552. + { \
  1553. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
  1554. + }
  1555. +
  1556. +#define DEVICE_H_WRAP0(ret, func) \
  1557. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This) \
  1558. + { \
  1559. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This); \
  1560. + }
  1561. +
  1562. +#define DEVICE_H_WRAP1(ret, func, type1) \
  1563. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1) \
  1564. + { \
  1565. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1); \
  1566. + }
  1567. +
  1568. +#define DEVICE_H_WRAP2(ret, func, type1, type2) \
  1569. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2) \
  1570. + { \
  1571. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2); \
  1572. + }
  1573. +
  1574. +#define DEVICE_H_WRAP3(ret, func, type1, type2, type3) \
  1575. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3) \
  1576. + { \
  1577. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3); \
  1578. + }
  1579. +
  1580. +#define DEVICE_H_WRAP4(ret, func, type1, type2, type3, type4) \
  1581. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
  1582. + { \
  1583. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4); \
  1584. + }
  1585. +
  1586. +#define DEVICE_H_WRAP5(ret, func, type1, type2, type3, type4, type5) \
  1587. + ret WINAPI DECLSPEC_HOTPATCH WineNineDevice9_ ## func(IDirect3DDevice9Ex *This, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
  1588. + { \
  1589. + return ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->func(This, arg1, arg2, arg3, arg4, arg5); \
  1590. + }
  1591. +
  1592. +SWAPCHAIN_WRAP2(HRESULT, QueryInterface, REFIID, void **)
  1593. +SWAPCHAIN_WRAP0(ULONG, AddRef)
  1594. +SWAPCHAIN_WRAP0(ULONG, Release)
  1595. +SWAPCHAIN_H_WRAP5(HRESULT, Present, const RECT *, const RECT *, HWND, const RGNDATA *, DWORD)
  1596. +SWAPCHAIN_WRAP1(HRESULT, GetFrontBufferData, IDirect3DSurface9 *)
  1597. +SWAPCHAIN_WRAP3(HRESULT, GetBackBuffer, UINT, D3DBACKBUFFER_TYPE, IDirect3DSurface9 **)
  1598. +SWAPCHAIN_WRAP1(HRESULT, GetRasterStatus, D3DRASTER_STATUS *)
  1599. +SWAPCHAIN_WRAP1(HRESULT, GetDisplayMode, D3DDISPLAYMODE *)
  1600. +SWAPCHAIN_WRAP1(HRESULT, GetDevice, IDirect3DDevice9 **)
  1601. +SWAPCHAIN_WRAP1(HRESULT, GetPresentParameters, D3DPRESENT_PARAMETERS *)
  1602. +SWAPCHAIN_WRAP1(HRESULT, GetLastPresentCount, UINT *)
  1603. +SWAPCHAIN_WRAP1(HRESULT, GetPresentStats, D3DPRESENTSTATS *)
  1604. +SWAPCHAIN_WRAP2(HRESULT, GetDisplayModeEx, D3DDISPLAYMODEEX *, D3DDISPLAYROTATION *)
  1605. +
  1606. +DEVICE_WRAP2(HRESULT, QueryInterface, REFIID, void **)
  1607. +DEVICE_WRAP0(ULONG, AddRef)
  1608. +DEVICE_H_WRAP0(ULONG, Release)
  1609. +DEVICE_WRAP0(HRESULT, TestCooperativeLevel)
  1610. +DEVICE_WRAP0(UINT, GetAvailableTextureMem)
  1611. +DEVICE_WRAP0(HRESULT, EvictManagedResources)
  1612. +DEVICE_WRAP1(HRESULT, GetDirect3D, IDirect3D9 **)
  1613. +DEVICE_WRAP1(HRESULT, GetDeviceCaps, D3DCAPS9 *)
  1614. +DEVICE_WRAP2(HRESULT, GetDisplayMode, UINT, D3DDISPLAYMODE*)
  1615. +DEVICE_WRAP1(HRESULT, GetCreationParameters, D3DDEVICE_CREATION_PARAMETERS *)
  1616. +DEVICE_WRAP3(HRESULT, SetCursorProperties, UINT, UINT, IDirect3DSurface9 *)
  1617. +DEVICE_WRAP3(void, SetCursorPosition, int, int, DWORD)
  1618. +DEVICE_WRAP1(BOOL, ShowCursor, BOOL)
  1619. +/*DEVICE_H_WRAP2(HRESULT, CreateAdditionalSwapChain, D3DPRESENT_PARAMETERS *, IDirect3DSwapChain9 **)*/
  1620. +/*DEVICE_H_WRAP2(HRESULT, GetSwapChain, UINT, IDirect3DSwapChain9 **)*/
  1621. +DEVICE_WRAP0(UINT, GetNumberOfSwapChains)
  1622. +DEVICE_H_WRAP1(HRESULT, Reset, D3DPRESENT_PARAMETERS *)
  1623. +DEVICE_H_WRAP4(HRESULT, Present, const RECT *, const RECT *, HWND, const RGNDATA *)
  1624. +DEVICE_WRAP4(HRESULT, GetBackBuffer, UINT, UINT, D3DBACKBUFFER_TYPE, IDirect3DSurface9 **)
  1625. +DEVICE_WRAP2(HRESULT, GetRasterStatus, UINT, D3DRASTER_STATUS *)
  1626. +DEVICE_WRAP1(HRESULT, SetDialogBoxMode, BOOL)
  1627. +DEVICE_H_WRAP3(void, SetGammaRamp, UINT, DWORD, const D3DGAMMARAMP *)
  1628. +DEVICE_WRAP2(void, GetGammaRamp, UINT, D3DGAMMARAMP *)
  1629. +DEVICE_WRAP8(HRESULT, CreateTexture, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DTexture9 **, HANDLE *)
  1630. +DEVICE_WRAP9(HRESULT, CreateVolumeTexture, UINT, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DVolumeTexture9 **, HANDLE *)
  1631. +DEVICE_WRAP7(HRESULT, CreateCubeTexture, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DCubeTexture9 **, HANDLE *)
  1632. +DEVICE_WRAP6(HRESULT, CreateVertexBuffer, UINT, DWORD, DWORD, D3DPOOL, IDirect3DVertexBuffer9 **, HANDLE *)
  1633. +DEVICE_WRAP6(HRESULT, CreateIndexBuffer, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DIndexBuffer9 **, HANDLE *)
  1634. +DEVICE_WRAP8(HRESULT, CreateRenderTarget, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, DWORD, BOOL, IDirect3DSurface9 **, HANDLE *)
  1635. +DEVICE_WRAP8(HRESULT, CreateDepthStencilSurface, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, DWORD, BOOL, IDirect3DSurface9 **, HANDLE *)
  1636. +DEVICE_WRAP4(HRESULT, UpdateSurface, IDirect3DSurface9 *, const RECT *, IDirect3DSurface9 *, const POINT *)
  1637. +DEVICE_WRAP2(HRESULT, UpdateTexture, IDirect3DBaseTexture9 *, IDirect3DBaseTexture9 *)
  1638. +DEVICE_WRAP2(HRESULT, GetRenderTargetData, IDirect3DSurface9 *, IDirect3DSurface9 *)
  1639. +DEVICE_WRAP2(HRESULT, GetFrontBufferData, UINT, IDirect3DSurface9 *)
  1640. +DEVICE_WRAP5(HRESULT, StretchRect, IDirect3DSurface9 *, const RECT *, IDirect3DSurface9 *, const RECT *, D3DTEXTUREFILTERTYPE)
  1641. +DEVICE_WRAP3(HRESULT, ColorFill, IDirect3DSurface9 *, const RECT *, D3DCOLOR)
  1642. +DEVICE_WRAP6(HRESULT, CreateOffscreenPlainSurface, UINT, UINT, D3DFORMAT, D3DPOOL, IDirect3DSurface9 **, HANDLE *)
  1643. +DEVICE_WRAP2(HRESULT, SetRenderTarget, DWORD, IDirect3DSurface9 *)
  1644. +DEVICE_WRAP2(HRESULT, GetRenderTarget, DWORD, IDirect3DSurface9 **)
  1645. +DEVICE_WRAP1(HRESULT, SetDepthStencilSurface, IDirect3DSurface9 *)
  1646. +DEVICE_WRAP1(HRESULT, GetDepthStencilSurface, IDirect3DSurface9 **)
  1647. +DEVICE_WRAP0(HRESULT, BeginScene)
  1648. +DEVICE_H_WRAP0(HRESULT, EndScene)
  1649. +DEVICE_WRAP6(HRESULT, Clear, DWORD, const D3DRECT *, DWORD, D3DCOLOR, float, DWORD)
  1650. +DEVICE_WRAP2(HRESULT, SetTransform, D3DTRANSFORMSTATETYPE, const D3DMATRIX *)
  1651. +DEVICE_WRAP2(HRESULT, GetTransform, D3DTRANSFORMSTATETYPE, D3DMATRIX *)
  1652. +DEVICE_WRAP2(HRESULT, MultiplyTransform, D3DTRANSFORMSTATETYPE, const D3DMATRIX *)
  1653. +DEVICE_WRAP1(HRESULT, SetViewport, const D3DVIEWPORT9 *)
  1654. +DEVICE_WRAP1(HRESULT, GetViewport, D3DVIEWPORT9 *)
  1655. +DEVICE_WRAP1(HRESULT, SetMaterial, const D3DMATERIAL9 *)
  1656. +DEVICE_WRAP1(HRESULT, GetMaterial, D3DMATERIAL9 *)
  1657. +DEVICE_WRAP2(HRESULT, SetLight, DWORD, const D3DLIGHT9 *)
  1658. +DEVICE_WRAP2(HRESULT, GetLight, DWORD, D3DLIGHT9 *)
  1659. +DEVICE_WRAP2(HRESULT, LightEnable, DWORD, BOOL)
  1660. +DEVICE_WRAP2(HRESULT, GetLightEnable, DWORD, BOOL *)
  1661. +DEVICE_WRAP2(HRESULT, SetClipPlane, DWORD, const float *)
  1662. +DEVICE_WRAP2(HRESULT, GetClipPlane, DWORD, float *)
  1663. +DEVICE_H_WRAP2(HRESULT, SetRenderState, D3DRENDERSTATETYPE, DWORD)
  1664. +DEVICE_WRAP2(HRESULT, GetRenderState, D3DRENDERSTATETYPE, DWORD *)
  1665. +DEVICE_WRAP2(HRESULT, CreateStateBlock, D3DSTATEBLOCKTYPE, IDirect3DStateBlock9 **)
  1666. +DEVICE_WRAP0(HRESULT, BeginStateBlock)
  1667. +DEVICE_WRAP1(HRESULT, EndStateBlock, IDirect3DStateBlock9 **)
  1668. +DEVICE_WRAP1(HRESULT, SetClipStatus, const D3DCLIPSTATUS9 *)
  1669. +DEVICE_WRAP1(HRESULT, GetClipStatus, D3DCLIPSTATUS9 *)
  1670. +DEVICE_WRAP2(HRESULT, GetTexture, DWORD, IDirect3DBaseTexture9 **)
  1671. +DEVICE_WRAP2(HRESULT, SetTexture, DWORD, IDirect3DBaseTexture9 *)
  1672. +DEVICE_WRAP3(HRESULT, GetTextureStageState, DWORD, D3DTEXTURESTAGESTATETYPE, DWORD *)
  1673. +DEVICE_WRAP3(HRESULT, SetTextureStageState, DWORD, D3DTEXTURESTAGESTATETYPE, DWORD)
  1674. +DEVICE_WRAP3(HRESULT, GetSamplerState, DWORD, D3DSAMPLERSTATETYPE, DWORD *)
  1675. +DEVICE_H_WRAP3(HRESULT, SetSamplerState, DWORD, D3DSAMPLERSTATETYPE, DWORD)
  1676. +DEVICE_WRAP1(HRESULT, ValidateDevice, DWORD *)
  1677. +DEVICE_WRAP2(HRESULT, SetPaletteEntries, UINT, const PALETTEENTRY *)
  1678. +DEVICE_WRAP2(HRESULT, GetPaletteEntries, UINT, PALETTEENTRY *)
  1679. +DEVICE_WRAP1(HRESULT, SetCurrentTexturePalette, UINT)
  1680. +DEVICE_WRAP1(HRESULT, GetCurrentTexturePalette, UINT *)
  1681. +DEVICE_WRAP1(HRESULT, SetScissorRect, const RECT *)
  1682. +DEVICE_WRAP1(HRESULT, GetScissorRect, RECT *)
  1683. +DEVICE_WRAP1(HRESULT, SetSoftwareVertexProcessing, BOOL)
  1684. +DEVICE_WRAP0(BOOL, GetSoftwareVertexProcessing)
  1685. +DEVICE_WRAP1(HRESULT, SetNPatchMode, float)
  1686. +DEVICE_WRAP0(float, GetNPatchMode)
  1687. +DEVICE_WRAP3(HRESULT, DrawPrimitive, D3DPRIMITIVETYPE, UINT, UINT)
  1688. +DEVICE_WRAP6(HRESULT, DrawIndexedPrimitive, D3DPRIMITIVETYPE, INT, UINT, UINT, UINT, UINT)
  1689. +DEVICE_WRAP4(HRESULT, DrawPrimitiveUP, D3DPRIMITIVETYPE, UINT, const void *, UINT)
  1690. +DEVICE_WRAP8(HRESULT, DrawIndexedPrimitiveUP, D3DPRIMITIVETYPE, UINT, UINT, UINT, const void *, D3DFORMAT, const void *, UINT)
  1691. +DEVICE_WRAP6(HRESULT, ProcessVertices, UINT, UINT, UINT, IDirect3DVertexBuffer9 *, IDirect3DVertexDeclaration9 *, DWORD)
  1692. +DEVICE_WRAP2(HRESULT, CreateVertexDeclaration, const D3DVERTEXELEMENT9 *, IDirect3DVertexDeclaration9 **)
  1693. +DEVICE_WRAP1(HRESULT, SetVertexDeclaration, IDirect3DVertexDeclaration9 *)
  1694. +DEVICE_WRAP1(HRESULT, GetVertexDeclaration, IDirect3DVertexDeclaration9 **)
  1695. +DEVICE_WRAP1(HRESULT, SetFVF, DWORD)
  1696. +DEVICE_WRAP1(HRESULT, GetFVF, DWORD *)
  1697. +DEVICE_WRAP2(HRESULT, CreateVertexShader, const DWORD *, IDirect3DVertexShader9 **)
  1698. +DEVICE_WRAP1(HRESULT, SetVertexShader, IDirect3DVertexShader9 *)
  1699. +DEVICE_WRAP1(HRESULT, GetVertexShader, IDirect3DVertexShader9 **)
  1700. +DEVICE_WRAP3(HRESULT, SetVertexShaderConstantF, UINT, const float *, UINT)
  1701. +DEVICE_WRAP3(HRESULT, GetVertexShaderConstantF, UINT, float *, UINT)
  1702. +DEVICE_WRAP3(HRESULT, SetVertexShaderConstantI, UINT, const int *, UINT)
  1703. +DEVICE_WRAP3(HRESULT, GetVertexShaderConstantI, UINT, int *, UINT)
  1704. +DEVICE_WRAP3(HRESULT, SetVertexShaderConstantB, UINT, const BOOL *, UINT)
  1705. +DEVICE_WRAP3(HRESULT, GetVertexShaderConstantB, UINT, BOOL *, UINT)
  1706. +DEVICE_WRAP4(HRESULT, SetStreamSource, UINT, IDirect3DVertexBuffer9 *, UINT, UINT)
  1707. +DEVICE_WRAP4(HRESULT, GetStreamSource, UINT, IDirect3DVertexBuffer9 **, UINT *, UINT *)
  1708. +DEVICE_WRAP2(HRESULT, SetStreamSourceFreq, UINT, UINT)
  1709. +DEVICE_WRAP2(HRESULT, GetStreamSourceFreq, UINT, UINT *)
  1710. +DEVICE_WRAP1(HRESULT, SetIndices, IDirect3DIndexBuffer9 *)
  1711. +DEVICE_WRAP1(HRESULT, GetIndices, IDirect3DIndexBuffer9 **)
  1712. +DEVICE_WRAP2(HRESULT, CreatePixelShader, const DWORD *, IDirect3DPixelShader9 **)
  1713. +DEVICE_WRAP1(HRESULT, SetPixelShader, IDirect3DPixelShader9 *)
  1714. +DEVICE_WRAP1(HRESULT, GetPixelShader, IDirect3DPixelShader9 **)
  1715. +DEVICE_WRAP3(HRESULT, SetPixelShaderConstantF, UINT, const float *, UINT)
  1716. +DEVICE_WRAP3(HRESULT, GetPixelShaderConstantF, UINT, float *, UINT)
  1717. +DEVICE_WRAP3(HRESULT, SetPixelShaderConstantI, UINT, const int *, UINT)
  1718. +DEVICE_WRAP3(HRESULT, GetPixelShaderConstantI, UINT, int *, UINT)
  1719. +DEVICE_WRAP3(HRESULT, SetPixelShaderConstantB, UINT, const BOOL *, UINT)
  1720. +DEVICE_WRAP3(HRESULT, GetPixelShaderConstantB, UINT, BOOL *, UINT)
  1721. +DEVICE_WRAP3(HRESULT, DrawRectPatch, UINT, const float *, const D3DRECTPATCH_INFO *)
  1722. +DEVICE_WRAP3(HRESULT, DrawTriPatch, UINT, const float *, const D3DTRIPATCH_INFO *)
  1723. +DEVICE_WRAP1(HRESULT, DeletePatch, UINT)
  1724. +DEVICE_WRAP2(HRESULT, CreateQuery, D3DQUERYTYPE, IDirect3DQuery9 **)
  1725. +DEVICE_WRAP4(HRESULT, SetConvolutionMonoKernel, UINT, UINT, float *, float *)
  1726. +DEVICE_WRAP8(HRESULT, ComposeRects, IDirect3DSurface9 *, IDirect3DSurface9 *, IDirect3DVertexBuffer9 *, UINT, IDirect3DVertexBuffer9 *, D3DCOMPOSERECTSOP, int, int)
  1727. +DEVICE_H_WRAP5(HRESULT, PresentEx, const RECT *, const RECT *, HWND, const RGNDATA *, DWORD)
  1728. +DEVICE_WRAP1(HRESULT, GetGPUThreadPriority, INT *)
  1729. +DEVICE_WRAP1(HRESULT, SetGPUThreadPriority, INT)
  1730. +DEVICE_WRAP1(HRESULT, WaitForVBlank, UINT)
  1731. +DEVICE_WRAP2(HRESULT, CheckResourceResidency, IDirect3DResource9 **, UINT32)
  1732. +DEVICE_WRAP1(HRESULT, SetMaximumFrameLatency, UINT)
  1733. +DEVICE_WRAP1(HRESULT, GetMaximumFrameLatency, UINT *)
  1734. +DEVICE_WRAP1(HRESULT, CheckDeviceState, HWND)
  1735. +DEVICE_WRAP9(HRESULT, CreateRenderTargetEx, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, DWORD, BOOL, IDirect3DSurface9 **, HANDLE *, DWORD)
  1736. +DEVICE_WRAP7(HRESULT, CreateOffscreenPlainSurfaceEx, UINT, UINT, D3DFORMAT, D3DPOOL, IDirect3DSurface9 **, HANDLE *, DWORD)
  1737. +DEVICE_WRAP9(HRESULT, CreateDepthStencilSurfaceEx, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, DWORD, BOOL, IDirect3DSurface9 **, HANDLE *, DWORD)
  1738. +DEVICE_H_WRAP2(HRESULT, ResetEx, D3DPRESENT_PARAMETERS *, D3DDISPLAYMODEEX *)
  1739. +DEVICE_WRAP3(HRESULT, GetDisplayModeEx, UINT, D3DDISPLAYMODEEX *, D3DDISPLAYROTATION *)
  1740. +
  1741. +IDirect3DSwapChain9ExVtbl WineNineSwapChain9Ex_vtable = {
  1742. + WineNineSwapChain9_QueryInterface,
  1743. + WineNineSwapChain9_AddRef,
  1744. + WineNineSwapChain9_Release,
  1745. + WineNineSwapChain9_Present,
  1746. + WineNineSwapChain9_GetFrontBufferData,
  1747. + WineNineSwapChain9_GetBackBuffer,
  1748. + WineNineSwapChain9_GetRasterStatus,
  1749. + WineNineSwapChain9_GetDisplayMode,
  1750. + WineNineSwapChain9_GetDevice,
  1751. + WineNineSwapChain9_GetPresentParameters,
  1752. + WineNineSwapChain9_GetLastPresentCount,
  1753. + WineNineSwapChain9_GetPresentStats,
  1754. + WineNineSwapChain9_GetDisplayModeEx
  1755. +};
  1756. +
  1757. +HRESULT WINAPI DECLSPEC_HOTPATCH WineNineDevice9_CreateAdditionalSwapChain(IDirect3DDevice9Ex *This, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain9 **pSwapChain)
  1758. +{
  1759. + HRESULT hr;
  1760. +
  1761. + hr = ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->CreateAdditionalSwapChain(This, pPresentationParameters, pSwapChain);
  1762. + if (FAILED(hr))
  1763. + return hr;
  1764. +
  1765. + (*pSwapChain)->lpVtbl = (IDirect3DSwapChain9Vtbl *)&WineNineSwapChain9Ex_vtable;
  1766. +
  1767. + return hr;
  1768. +}
  1769. +
  1770. +HRESULT WINAPI DECLSPEC_HOTPATCH WineNineDevice9_GetSwapChain(IDirect3DDevice9Ex *This, UINT iSwapChain, IDirect3DSwapChain9 **pSwapChain)
  1771. +{
  1772. + HRESULT hr;
  1773. +
  1774. + hr = ((IDirect3DDevice9Ex_Minor1 *)This)->lpVtbl_internal->GetSwapChain(This, iSwapChain, pSwapChain);
  1775. + if (FAILED(hr))
  1776. + return hr;
  1777. +
  1778. + (*pSwapChain)->lpVtbl = (IDirect3DSwapChain9Vtbl *)&WineNineSwapChain9Ex_vtable;
  1779. +
  1780. + return hr;
  1781. +}
  1782. +
  1783. +
  1784. +IDirect3DDevice9ExVtbl WineNineDevice9_vtable = {
  1785. + WineNineDevice9_QueryInterface,
  1786. + WineNineDevice9_AddRef,
  1787. + WineNineDevice9_Release,
  1788. + WineNineDevice9_TestCooperativeLevel,
  1789. + WineNineDevice9_GetAvailableTextureMem,
  1790. + WineNineDevice9_EvictManagedResources,
  1791. + WineNineDevice9_GetDirect3D,
  1792. + WineNineDevice9_GetDeviceCaps,
  1793. + WineNineDevice9_GetDisplayMode,
  1794. + WineNineDevice9_GetCreationParameters,
  1795. + WineNineDevice9_SetCursorProperties,
  1796. + WineNineDevice9_SetCursorPosition,
  1797. + WineNineDevice9_ShowCursor,
  1798. + WineNineDevice9_CreateAdditionalSwapChain,
  1799. + WineNineDevice9_GetSwapChain,
  1800. + WineNineDevice9_GetNumberOfSwapChains,
  1801. + WineNineDevice9_Reset,
  1802. + WineNineDevice9_Present,
  1803. + WineNineDevice9_GetBackBuffer,
  1804. + WineNineDevice9_GetRasterStatus,
  1805. + WineNineDevice9_SetDialogBoxMode,
  1806. + WineNineDevice9_SetGammaRamp,
  1807. + WineNineDevice9_GetGammaRamp,
  1808. + WineNineDevice9_CreateTexture,
  1809. + WineNineDevice9_CreateVolumeTexture,
  1810. + WineNineDevice9_CreateCubeTexture,
  1811. + WineNineDevice9_CreateVertexBuffer,
  1812. + WineNineDevice9_CreateIndexBuffer,
  1813. + WineNineDevice9_CreateRenderTarget,
  1814. + WineNineDevice9_CreateDepthStencilSurface,
  1815. + WineNineDevice9_UpdateSurface,
  1816. + WineNineDevice9_UpdateTexture,
  1817. + WineNineDevice9_GetRenderTargetData,
  1818. + WineNineDevice9_GetFrontBufferData,
  1819. + WineNineDevice9_StretchRect,
  1820. + WineNineDevice9_ColorFill,
  1821. + WineNineDevice9_CreateOffscreenPlainSurface,
  1822. + WineNineDevice9_SetRenderTarget,
  1823. + WineNineDevice9_GetRenderTarget,
  1824. + WineNineDevice9_SetDepthStencilSurface,
  1825. + WineNineDevice9_GetDepthStencilSurface,
  1826. + WineNineDevice9_BeginScene,
  1827. + WineNineDevice9_EndScene,
  1828. + WineNineDevice9_Clear,
  1829. + WineNineDevice9_SetTransform,
  1830. + WineNineDevice9_GetTransform,
  1831. + WineNineDevice9_MultiplyTransform,
  1832. + WineNineDevice9_SetViewport,
  1833. + WineNineDevice9_GetViewport,
  1834. + WineNineDevice9_SetMaterial,
  1835. + WineNineDevice9_GetMaterial,
  1836. + WineNineDevice9_SetLight,
  1837. + WineNineDevice9_GetLight,
  1838. + WineNineDevice9_LightEnable,
  1839. + WineNineDevice9_GetLightEnable,
  1840. + WineNineDevice9_SetClipPlane,
  1841. + WineNineDevice9_GetClipPlane,
  1842. + WineNineDevice9_SetRenderState,
  1843. + WineNineDevice9_GetRenderState,
  1844. + WineNineDevice9_CreateStateBlock,
  1845. + WineNineDevice9_BeginStateBlock,
  1846. + WineNineDevice9_EndStateBlock,
  1847. + WineNineDevice9_SetClipStatus,
  1848. + WineNineDevice9_GetClipStatus,
  1849. + WineNineDevice9_GetTexture,
  1850. + WineNineDevice9_SetTexture,
  1851. + WineNineDevice9_GetTextureStageState,
  1852. + WineNineDevice9_SetTextureStageState,
  1853. + WineNineDevice9_GetSamplerState,
  1854. + WineNineDevice9_SetSamplerState,
  1855. + WineNineDevice9_ValidateDevice,
  1856. + WineNineDevice9_SetPaletteEntries,
  1857. + WineNineDevice9_GetPaletteEntries,
  1858. + WineNineDevice9_SetCurrentTexturePalette,
  1859. + WineNineDevice9_GetCurrentTexturePalette,
  1860. + WineNineDevice9_SetScissorRect,
  1861. + WineNineDevice9_GetScissorRect,
  1862. + WineNineDevice9_SetSoftwareVertexProcessing,
  1863. + WineNineDevice9_GetSoftwareVertexProcessing,
  1864. + WineNineDevice9_SetNPatchMode,
  1865. + WineNineDevice9_GetNPatchMode,
  1866. + WineNineDevice9_DrawPrimitive,
  1867. + WineNineDevice9_DrawIndexedPrimitive,
  1868. + WineNineDevice9_DrawPrimitiveUP,
  1869. + WineNineDevice9_DrawIndexedPrimitiveUP,
  1870. + WineNineDevice9_ProcessVertices,
  1871. + WineNineDevice9_CreateVertexDeclaration,
  1872. + WineNineDevice9_SetVertexDeclaration,
  1873. + WineNineDevice9_GetVertexDeclaration,
  1874. + WineNineDevice9_SetFVF,
  1875. + WineNineDevice9_GetFVF,
  1876. + WineNineDevice9_CreateVertexShader,
  1877. + WineNineDevice9_SetVertexShader,
  1878. + WineNineDevice9_GetVertexShader,
  1879. + WineNineDevice9_SetVertexShaderConstantF,
  1880. + WineNineDevice9_GetVertexShaderConstantF,
  1881. + WineNineDevice9_SetVertexShaderConstantI,
  1882. + WineNineDevice9_GetVertexShaderConstantI,
  1883. + WineNineDevice9_SetVertexShaderConstantB,
  1884. + WineNineDevice9_GetVertexShaderConstantB,
  1885. + WineNineDevice9_SetStreamSource,
  1886. + WineNineDevice9_GetStreamSource,
  1887. + WineNineDevice9_SetStreamSourceFreq,
  1888. + WineNineDevice9_GetStreamSourceFreq,
  1889. + WineNineDevice9_SetIndices,
  1890. + WineNineDevice9_GetIndices,
  1891. + WineNineDevice9_CreatePixelShader,
  1892. + WineNineDevice9_SetPixelShader,
  1893. + WineNineDevice9_GetPixelShader,
  1894. + WineNineDevice9_SetPixelShaderConstantF,
  1895. + WineNineDevice9_GetPixelShaderConstantF,
  1896. + WineNineDevice9_SetPixelShaderConstantI,
  1897. + WineNineDevice9_GetPixelShaderConstantI,
  1898. + WineNineDevice9_SetPixelShaderConstantB,
  1899. + WineNineDevice9_GetPixelShaderConstantB,
  1900. + WineNineDevice9_DrawRectPatch,
  1901. + WineNineDevice9_DrawTriPatch,
  1902. + WineNineDevice9_DeletePatch,
  1903. + WineNineDevice9_CreateQuery,
  1904. + WineNineDevice9_SetConvolutionMonoKernel,
  1905. + WineNineDevice9_ComposeRects,
  1906. + WineNineDevice9_PresentEx,
  1907. + WineNineDevice9_GetGPUThreadPriority,
  1908. + WineNineDevice9_SetGPUThreadPriority,
  1909. + WineNineDevice9_WaitForVBlank,
  1910. + WineNineDevice9_CheckResourceResidency,
  1911. + WineNineDevice9_SetMaximumFrameLatency,
  1912. + WineNineDevice9_GetMaximumFrameLatency,
  1913. + WineNineDevice9_CheckDeviceState,
  1914. + WineNineDevice9_CreateRenderTargetEx,
  1915. + WineNineDevice9_CreateOffscreenPlainSurfaceEx,
  1916. + WineNineDevice9_CreateDepthStencilSurfaceEx,
  1917. + WineNineDevice9_ResetEx,
  1918. + WineNineDevice9_GetDisplayModeEx
  1919. +};
  1920. +
  1921. +IDirect3DDevice9ExVtbl *get_device_vtable()
  1922. +{
  1923. + return &WineNineDevice9_vtable;
  1924. +}
  1925. diff --git a/dlls/d3d9-nine/device_wrap.h b/dlls/d3d9-nine/device_wrap.h
  1926. new file mode 100644
  1927. index 0000000000..8f5e7206a0
  1928. --- /dev/null
  1929. +++ b/dlls/d3d9-nine/device_wrap.h
  1930. @@ -0,0 +1,26 @@
  1931. +/*
  1932. + * Copyright 2016 Axel Davy
  1933. + *
  1934. + * This library is free software; you can redistribute it and/or
  1935. + * modify it under the terms of the GNU Lesser General Public
  1936. + * License as published by the Free Software Foundation; either
  1937. + * version 2.1 of the License, or (at your option) any later version.
  1938. + *
  1939. + * This library is distributed in the hope that it will be useful,
  1940. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1941. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1942. + * Lesser General Public License for more details.
  1943. + *
  1944. + * You should have received a copy of the GNU Lesser General Public
  1945. + * License along with this library; if not, write to the Free Software
  1946. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  1947. + */
  1948. +
  1949. +#ifndef __NINE_DEVICE_WRAP_H
  1950. +#define __NINE_DEVICE_WRAP_H
  1951. +
  1952. +#include <d3dadapter/d3dadapter9.h>
  1953. +
  1954. +IDirect3DDevice9ExVtbl *get_device_vtable(void);
  1955. +
  1956. +#endif /* __NINE_DEVICE_WRAP_H */
  1957. diff --git a/dlls/d3d9-nine/dri3.c b/dlls/d3d9-nine/dri3.c
  1958. new file mode 100644
  1959. index 0000000000..3946e7f8bf
  1960. --- /dev/null
  1961. +++ b/dlls/d3d9-nine/dri3.c
  1962. @@ -0,0 +1,1426 @@
  1963. +/*
  1964. + * Wine DRI3 interface
  1965. + *
  1966. + * Copyright 2014-2015 Axel Davy
  1967. + * Copyright 2015 Patrick Rudolph
  1968. + *
  1969. + * This library is free software; you can redistribute it and/or
  1970. + * modify it under the terms of the GNU Lesser General Public
  1971. + * License as published by the Free Software Foundation; either
  1972. + * version 2.1 of the License, or (at your option) any later version.
  1973. + *
  1974. + * This library is distributed in the hope that it will be useful,
  1975. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1976. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1977. + * Lesser General Public License for more details.
  1978. + *
  1979. + * You should have received a copy of the GNU Lesser General Public
  1980. + * License along with this library; if not, write to the Free Software
  1981. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  1982. + */
  1983. +
  1984. +
  1985. +#include "config.h"
  1986. +#include "wine/debug.h"
  1987. +
  1988. +WINE_DEFAULT_DEBUG_CHANNEL(d3d9nine);
  1989. +
  1990. +#include "dri3.h"
  1991. +
  1992. +#include <fcntl.h>
  1993. +#include <unistd.h>
  1994. +#include <pthread.h>
  1995. +
  1996. +#include <X11/Xlib-xcb.h>
  1997. +#include <xcb/dri3.h>
  1998. +#include <xcb/present.h>
  1999. +
  2000. +#include "winbase.h"
  2001. +
  2002. +#ifdef D3D9NINE_DRI2
  2003. +#include <sys/ioctl.h>
  2004. +
  2005. +#define BOOL X_BOOL
  2006. +#define BYTE X_BYTE
  2007. +#define INT8 X_INT8
  2008. +#define INT16 X_INT16
  2009. +#define INT32 X_INT32
  2010. +#define INT64 X_INT64
  2011. +#include <X11/Xmd.h>
  2012. +#undef BOOL
  2013. +#undef BYTE
  2014. +#undef INT8
  2015. +#undef INT16
  2016. +#undef INT32
  2017. +#undef INT64
  2018. +#undef LONG64
  2019. +
  2020. +#include <X11/Xlibint.h>
  2021. +#include <X11/extensions/dri2tokens.h>
  2022. +#include <X11/extensions/dri2proto.h>
  2023. +#include <X11/extensions/extutil.h>
  2024. +#define GL_GLEXT_PROTOTYPES 1
  2025. +#define EGL_EGLEXT_PROTOTYPES 1
  2026. +#define GL_GLEXT_LEGACY 1
  2027. +
  2028. +/* workaround for broken ABI on x86_64 due to windef.h */
  2029. +#undef APIENTRY
  2030. +#undef APIENTRYP
  2031. +#include <GL/gl.h>
  2032. +
  2033. +/* workaround gl header bug */
  2034. +#define glBlendColor glBlendColorLEV
  2035. +#define glBlendEquation glBlendEquationLEV
  2036. +#include <GL/glext.h>
  2037. +#include <EGL/egl.h>
  2038. +#include <EGL/eglext.h>
  2039. +#include <libdrm/drm_fourcc.h>
  2040. +#include <libdrm/drm.h>
  2041. +
  2042. +static EGLDisplay display = NULL;
  2043. +static int display_ref = 0;
  2044. +
  2045. +struct DRI2priv {
  2046. + Display *dpy;
  2047. + EGLDisplay display;
  2048. + EGLContext context;
  2049. + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_func;
  2050. + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR_func;
  2051. + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR_func;
  2052. +};
  2053. +#endif
  2054. +
  2055. +struct PRESENTPriv {
  2056. + xcb_connection_t *xcb_connection;
  2057. + xcb_connection_t *xcb_connection_bis; /* to avoid libxcb thread bugs, use a different connection to present pixmaps */
  2058. + XID window;
  2059. + uint64_t last_msc;
  2060. + uint64_t last_target;
  2061. + uint32_t last_serial_given;
  2062. + xcb_special_event_t *special_event;
  2063. + PRESENTPixmapPriv *first_present_priv;
  2064. + int pixmap_present_pending;
  2065. + BOOL idle_notify_since_last_check;
  2066. + BOOL notify_with_serial_pending;
  2067. + CRITICAL_SECTION mutex_present; /* protect readind/writing present_priv things */
  2068. + CRITICAL_SECTION mutex_xcb_wait;
  2069. + BOOL xcb_wait;
  2070. +};
  2071. +
  2072. +struct PRESENTPixmapPriv {
  2073. + PRESENTpriv *present_priv;
  2074. + Pixmap pixmap;
  2075. + BOOL released;
  2076. + unsigned int width;
  2077. + unsigned int height;
  2078. + unsigned int depth;
  2079. + unsigned int present_complete_pending;
  2080. + uint32_t serial;
  2081. +#ifdef D3D9NINE_DRI2
  2082. + struct {
  2083. + BOOL is_dri2;
  2084. + struct DRI2priv *dri2_priv;
  2085. + GLuint fbo_read;
  2086. + GLuint fbo_write;
  2087. + GLuint texture_read;
  2088. + GLuint texture_write;
  2089. + } dri2_info;
  2090. +#endif
  2091. + BOOL last_present_was_flip;
  2092. + PRESENTPixmapPriv *next;
  2093. +};
  2094. +
  2095. +BOOL DRI3CheckExtension(Display *dpy, int major, int minor)
  2096. +{
  2097. + xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
  2098. + xcb_dri3_query_version_cookie_t dri3_cookie;
  2099. + xcb_dri3_query_version_reply_t *dri3_reply;
  2100. + xcb_generic_error_t *error;
  2101. + const xcb_query_extension_reply_t *extension;
  2102. + int fd;
  2103. +
  2104. + xcb_prefetch_extension_data(xcb_connection, &xcb_dri3_id);
  2105. +
  2106. + extension = xcb_get_extension_data(xcb_connection, &xcb_dri3_id);
  2107. + if (!(extension && extension->present))
  2108. + {
  2109. + ERR("DRI3 extension is not present\n");
  2110. + return FALSE;
  2111. + }
  2112. +
  2113. + dri3_cookie = xcb_dri3_query_version(xcb_connection, major, minor);
  2114. +
  2115. + dri3_reply = xcb_dri3_query_version_reply(xcb_connection, dri3_cookie, &error);
  2116. + if (!dri3_reply)
  2117. + {
  2118. + free(error);
  2119. + ERR("Issue getting requested version of DRI3: %d,%d\n", major, minor);
  2120. + return FALSE;
  2121. + }
  2122. +
  2123. + if (!DRI3Open(dpy, DefaultScreen(dpy), &fd))
  2124. + {
  2125. + ERR("DRI3 advertised, but not working\n");
  2126. + return FALSE;
  2127. + }
  2128. + close(fd);
  2129. +
  2130. + TRACE("DRI3 version %d,%d found. %d %d requested\n", major, minor,
  2131. + (int)dri3_reply->major_version, (int)dri3_reply->minor_version);
  2132. + free(dri3_reply);
  2133. +
  2134. + return TRUE;
  2135. +}
  2136. +
  2137. +#ifdef D3D9NINE_DRI2
  2138. +
  2139. +BOOL DRI2FallbackInit(Display *dpy, struct DRI2priv **priv)
  2140. +{
  2141. + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_func;
  2142. + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR_func;
  2143. + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT_func;
  2144. + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR_func;
  2145. + EGLint major, minor;
  2146. + EGLConfig config;
  2147. + EGLContext context;
  2148. + EGLint i;
  2149. + EGLBoolean b;
  2150. + EGLenum current_api = 0;
  2151. + const char *extensions;
  2152. + EGLint config_attribs[] = {
  2153. + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
  2154. + EGL_NONE
  2155. + };
  2156. + EGLint context_compatibility_attribs[] = {
  2157. + EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
  2158. + EGL_NONE
  2159. + };
  2160. +
  2161. + current_api = eglQueryAPI();
  2162. + eglGetPlatformDisplayEXT_func = (PFNEGLGETPLATFORMDISPLAYEXTPROC)
  2163. + eglGetProcAddress("eglGetPlatformDisplayEXT");
  2164. +
  2165. + if (!eglGetPlatformDisplayEXT_func)
  2166. + return FALSE;
  2167. + if (!display)
  2168. + display = eglGetPlatformDisplayEXT_func(EGL_PLATFORM_X11_EXT, dpy, NULL);
  2169. + if (!display)
  2170. + return FALSE;
  2171. + /* count references on display for multi device setups */
  2172. + display_ref++;
  2173. +
  2174. + if (eglInitialize(display, &major, &minor) != EGL_TRUE)
  2175. + goto clean_egl_display;
  2176. +
  2177. + extensions = eglQueryString(display, EGL_CLIENT_APIS);
  2178. + if (!extensions || !strstr(extensions, "OpenGL"))
  2179. + goto clean_egl_display;
  2180. +
  2181. + extensions = eglQueryString(display, EGL_EXTENSIONS);
  2182. + if (!extensions || !strstr(extensions, "EGL_EXT_image_dma_buf_import") ||
  2183. + !strstr(extensions, "EGL_KHR_create_context") ||
  2184. + !strstr(extensions, "EGL_KHR_surfaceless_context") ||
  2185. + !strstr(extensions, "EGL_KHR_image_base"))
  2186. + goto clean_egl_display;
  2187. +
  2188. + if (!eglChooseConfig(display, config_attribs, &config, 1, &i))
  2189. + goto clean_egl_display;
  2190. +
  2191. + b = eglBindAPI(EGL_OPENGL_API);
  2192. + if (b == EGL_FALSE)
  2193. + goto clean_egl_display;
  2194. + context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_compatibility_attribs);
  2195. + if (context == EGL_NO_CONTEXT)
  2196. + goto clean_egl_display;
  2197. +
  2198. + glEGLImageTargetTexture2DOES_func = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
  2199. + eglGetProcAddress("glEGLImageTargetTexture2DOES");
  2200. +
  2201. + eglCreateImageKHR_func = (PFNEGLCREATEIMAGEKHRPROC)
  2202. + eglGetProcAddress("eglCreateImageKHR");
  2203. +
  2204. + eglDestroyImageKHR_func = (PFNEGLDESTROYIMAGEKHRPROC)
  2205. + eglGetProcAddress("eglDestroyImageKHR");
  2206. +
  2207. + if (!eglCreateImageKHR_func ||
  2208. + !glEGLImageTargetTexture2DOES_func ||
  2209. + !eglDestroyImageKHR_func)
  2210. + {
  2211. + ERR("eglGetProcAddress failed !");
  2212. + goto clean_egl;
  2213. + }
  2214. +
  2215. + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  2216. +
  2217. + *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  2218. + sizeof(struct DRI2priv));
  2219. + if (!*priv)
  2220. + goto clean_egl;
  2221. + (*priv)->dpy = dpy;
  2222. + (*priv)->display = display;
  2223. + (*priv)->context = context;
  2224. + (*priv)->glEGLImageTargetTexture2DOES_func = glEGLImageTargetTexture2DOES_func;
  2225. + (*priv)->eglCreateImageKHR_func = eglCreateImageKHR_func;
  2226. + (*priv)->eglDestroyImageKHR_func = eglDestroyImageKHR_func;
  2227. + eglBindAPI(current_api);
  2228. + return TRUE;
  2229. +
  2230. +clean_egl:
  2231. + eglDestroyContext(display, context);
  2232. +
  2233. +clean_egl_display:
  2234. + eglTerminate(display);
  2235. + eglBindAPI(current_api);
  2236. + return FALSE;
  2237. +}
  2238. +
  2239. +/* hypothesis: at this step all textures, etc are destroyed */
  2240. +void DRI2FallbackDestroy(struct DRI2priv *priv)
  2241. +{
  2242. + EGLenum current_api;
  2243. + current_api = eglQueryAPI();
  2244. + eglBindAPI(EGL_OPENGL_API);
  2245. + eglMakeCurrent(priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  2246. + eglDestroyContext(priv->display, priv->context);
  2247. + if (display)
  2248. + {
  2249. + /* destroy display connection with last device */
  2250. + display_ref--;
  2251. + if (!display_ref)
  2252. + {
  2253. + eglTerminate(display);
  2254. + display = NULL;
  2255. + }
  2256. + }
  2257. + eglBindAPI(current_api);
  2258. + HeapFree(GetProcessHeap(), 0, priv);
  2259. +}
  2260. +
  2261. +BOOL DRI2FallbackCheckSupport(Display *dpy)
  2262. +{
  2263. + struct DRI2priv *priv;
  2264. + int fd;
  2265. + if (!DRI2FallbackInit(dpy, &priv))
  2266. + return FALSE;
  2267. + DRI2FallbackDestroy(priv);
  2268. + if (!DRI2FallbackOpen(dpy, DefaultScreen(dpy), &fd))
  2269. + return FALSE;
  2270. + close(fd);
  2271. + return TRUE;
  2272. +}
  2273. +
  2274. +#endif
  2275. +
  2276. +BOOL PRESENTCheckExtension(Display *dpy, int major, int minor)
  2277. +{
  2278. + xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
  2279. + xcb_present_query_version_cookie_t present_cookie;
  2280. + xcb_present_query_version_reply_t *present_reply;
  2281. + xcb_generic_error_t *error;
  2282. + const xcb_query_extension_reply_t *extension;
  2283. +
  2284. + xcb_prefetch_extension_data(xcb_connection, &xcb_present_id);
  2285. +
  2286. + extension = xcb_get_extension_data(xcb_connection, &xcb_present_id);
  2287. + if (!(extension && extension->present))
  2288. + {
  2289. + ERR("PRESENT extension is not present\n");
  2290. + return FALSE;
  2291. + }
  2292. +
  2293. + present_cookie = xcb_present_query_version(xcb_connection, major, minor);
  2294. +
  2295. + present_reply = xcb_present_query_version_reply(xcb_connection, present_cookie, &error);
  2296. + if (!present_reply)
  2297. + {
  2298. + free(error);
  2299. + ERR("Issue getting requested version of PRESENT: %d,%d\n", major, minor);
  2300. + return FALSE;
  2301. + }
  2302. +
  2303. + TRACE("PRESENT version %d,%d found. %u %u requested\n", major, minor,
  2304. + present_reply->major_version, present_reply->minor_version);
  2305. +
  2306. + free(present_reply);
  2307. +
  2308. + return TRUE;
  2309. +}
  2310. +
  2311. +BOOL DRI3Open(Display *dpy, int screen, int *device_fd)
  2312. +{
  2313. + xcb_dri3_open_cookie_t cookie;
  2314. + xcb_dri3_open_reply_t *reply;
  2315. + xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
  2316. + int fd;
  2317. + Window root = RootWindow(dpy, screen);
  2318. +
  2319. + cookie = xcb_dri3_open(xcb_connection, root, 0);
  2320. +
  2321. + reply = xcb_dri3_open_reply(xcb_connection, cookie, NULL);
  2322. + if (!reply)
  2323. + return FALSE;
  2324. +
  2325. + if (reply->nfd != 1)
  2326. + {
  2327. + free(reply);
  2328. + return FALSE;
  2329. + }
  2330. +
  2331. + fd = xcb_dri3_open_reply_fds(xcb_connection, reply)[0];
  2332. + fcntl(fd, F_SETFD, FD_CLOEXEC);
  2333. +
  2334. + *device_fd = fd;
  2335. + free(reply);
  2336. +
  2337. + return TRUE;
  2338. +}
  2339. +
  2340. +#ifdef D3D9NINE_DRI2
  2341. +
  2342. +static XExtensionInfo _dri2_info_data;
  2343. +static XExtensionInfo *dri2_info = &_dri2_info_data;
  2344. +static char dri2_name[] = DRI2_NAME;
  2345. +
  2346. +#define DRI2CheckExtension(dpy, i, val) \
  2347. + XextCheckExtension(dpy, i, dri2_name, val)
  2348. +
  2349. +static int close_display(Display *dpy, XExtCodes *codes);
  2350. +static Bool wire_to_event(Display *dpy, XEvent *re, xEvent *event);
  2351. +static Status event_to_wire(Display *dpy, XEvent *re, xEvent *event);
  2352. +static int error( Display *dpy, xError *err, XExtCodes *codes, int *ret_code );
  2353. +
  2354. +static XExtensionHooks dri2_hooks = {
  2355. + NULL, /* create_gc */
  2356. + NULL, /* copy_gc */
  2357. + NULL, /* flush_gc */
  2358. + NULL, /* free_gc */
  2359. + NULL, /* create_font */
  2360. + NULL, /* free_font */
  2361. + close_display, /* close_display */
  2362. + wire_to_event, /* wire_to_event */
  2363. + event_to_wire, /* event_to_wire */
  2364. + error, /* error */
  2365. + NULL, /* error_string */
  2366. +};
  2367. +static XEXT_GENERATE_CLOSE_DISPLAY(close_display, dri2_info);
  2368. +static XEXT_GENERATE_FIND_DISPLAY(find_display, dri2_info,
  2369. + dri2_name, &dri2_hooks, 0, NULL);
  2370. +static Bool wire_to_event(Display *dpy, XEvent *re, xEvent *event)
  2371. +{
  2372. + XExtDisplayInfo *info = find_display(dpy);
  2373. + DRI2CheckExtension(dpy, info, False);
  2374. + TRACE("dri2 wire_to_event\n");
  2375. + return False;
  2376. +}
  2377. +
  2378. +static Status event_to_wire(Display *dpy, XEvent *re, xEvent *event)
  2379. +{
  2380. + XExtDisplayInfo *info = find_display(dpy);
  2381. + DRI2CheckExtension(dpy, info, False);
  2382. + TRACE("dri2 event_to_wire\n");
  2383. + return False;
  2384. +}
  2385. +
  2386. +static int error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
  2387. +{
  2388. + TRACE("dri2 error\n");
  2389. + return False;
  2390. +}
  2391. +
  2392. +#define XALIGN(x) (((x) + 3) & (~3))
  2393. +
  2394. +static BOOL DRI2Connect(Display *dpy, XID window, unsigned driver_type, char **device)
  2395. +{
  2396. + XExtDisplayInfo *info = find_display(dpy);
  2397. + xDRI2ConnectReply rep;
  2398. + xDRI2ConnectReq *req;
  2399. + int dev_len, driv_len;
  2400. + char *driver;
  2401. +
  2402. + DRI2CheckExtension(dpy, info, False);
  2403. +
  2404. + *device = NULL;
  2405. +
  2406. + LockDisplay(dpy);
  2407. + GetReq(DRI2Connect, req);
  2408. + req->reqType = info->codes->major_opcode;
  2409. + req->dri2ReqType = X_DRI2Connect;
  2410. + req->window = window;
  2411. + req->driverType = driver_type;
  2412. + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
  2413. + {
  2414. + UnlockDisplay(dpy);
  2415. + SyncHandle();
  2416. + return False;
  2417. + }
  2418. +
  2419. + /* check string lengths */
  2420. + dev_len = rep.deviceNameLength;
  2421. + driv_len = rep.driverNameLength;
  2422. + if (dev_len == 0 || driv_len == 0)
  2423. + {
  2424. + _XEatData(dpy, XALIGN(dev_len) + XALIGN(driv_len));
  2425. + UnlockDisplay(dpy);
  2426. + SyncHandle();
  2427. + return False;
  2428. + }
  2429. +
  2430. + /* read out driver */
  2431. + driver = HeapAlloc(GetProcessHeap(), 0, driv_len + 1);
  2432. + if (!driver)
  2433. + {
  2434. + _XEatData(dpy, XALIGN(dev_len) + XALIGN(driv_len));
  2435. + UnlockDisplay(dpy);
  2436. + SyncHandle();
  2437. + return False;
  2438. + }
  2439. + _XReadPad(dpy, driver, driv_len);
  2440. + HeapFree(GetProcessHeap(), 0, driver); /* we don't need the driver */
  2441. +
  2442. + /* read out device */
  2443. + *device = HeapAlloc(GetProcessHeap(), 0, dev_len + 1);
  2444. + if (!*device)
  2445. + {
  2446. + _XEatData(dpy, XALIGN(dev_len));
  2447. + UnlockDisplay(dpy);
  2448. + SyncHandle();
  2449. + return False;
  2450. + }
  2451. + _XReadPad(dpy, *device, dev_len);
  2452. + (*device)[dev_len] = '\0';
  2453. +
  2454. + UnlockDisplay(dpy);
  2455. + SyncHandle();
  2456. +
  2457. + return True;
  2458. +}
  2459. +
  2460. +static Bool DRI2Authenticate(Display *dpy, XID window, uint32_t token)
  2461. +{
  2462. + XExtDisplayInfo *info = find_display(dpy);
  2463. + xDRI2AuthenticateReply rep;
  2464. + xDRI2AuthenticateReq *req;
  2465. +
  2466. + DRI2CheckExtension(dpy, info, False);
  2467. +
  2468. + LockDisplay(dpy);
  2469. + GetReq(DRI2Authenticate, req);
  2470. + req->reqType = info->codes->major_opcode;
  2471. + req->dri2ReqType = X_DRI2Authenticate;
  2472. + req->window = window;
  2473. + req->magic = token;
  2474. + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
  2475. + {
  2476. + UnlockDisplay(dpy);
  2477. + SyncHandle();
  2478. + return False;
  2479. + }
  2480. + UnlockDisplay(dpy);
  2481. + SyncHandle();
  2482. +
  2483. + return rep.authenticated ? True : False;
  2484. +}
  2485. +
  2486. +BOOL DRI2FallbackOpen(Display *dpy, int screen, int *device_fd)
  2487. +{
  2488. + char *device;
  2489. + int fd;
  2490. + Window root = RootWindow(dpy, screen);
  2491. + drm_auth_t auth;
  2492. +
  2493. + if (!DRI2Connect(dpy, root, DRI2DriverDRI, &device))
  2494. + return FALSE;
  2495. +
  2496. + fd = open(device, O_RDWR);
  2497. + HeapFree(GetProcessHeap(), 0, device);
  2498. + if (fd < 0)
  2499. + return FALSE;
  2500. +
  2501. + if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth) != 0)
  2502. + {
  2503. + close(fd);
  2504. + return FALSE;
  2505. + }
  2506. +
  2507. + if (!DRI2Authenticate(dpy, root, auth.magic))
  2508. + {
  2509. + close(fd);
  2510. + return FALSE;
  2511. + }
  2512. +
  2513. + *device_fd = fd;
  2514. +
  2515. + return TRUE;
  2516. +}
  2517. +
  2518. +#endif
  2519. +
  2520. +
  2521. +BOOL DRI3PixmapFromDmaBuf(Display *dpy, int screen, int fd, int width, int height,
  2522. + int stride, int depth, int bpp, Pixmap *pixmap)
  2523. +{
  2524. + xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
  2525. + Window root = RootWindow(dpy, screen);
  2526. + xcb_void_cookie_t cookie;
  2527. + xcb_generic_error_t *error;
  2528. +
  2529. + cookie = xcb_dri3_pixmap_from_buffer_checked(xcb_connection,
  2530. + (*pixmap = xcb_generate_id(xcb_connection)), root, 0,
  2531. + width, height, stride, depth, bpp, fd);
  2532. +
  2533. + error = xcb_request_check(xcb_connection, cookie); /* performs a flush */
  2534. + if (error)
  2535. + {
  2536. + ERR("Error using DRI3 to convert a DmaBufFd to pixmap\n");
  2537. + return FALSE;
  2538. + }
  2539. + return TRUE;
  2540. +}
  2541. +
  2542. +BOOL DRI3DmaBufFromPixmap(Display *dpy, Pixmap pixmap, int *fd, int *width, int *height,
  2543. + int *stride, int *depth, int *bpp)
  2544. +{
  2545. + xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
  2546. + xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
  2547. + xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
  2548. +
  2549. + bp_cookie = xcb_dri3_buffer_from_pixmap(xcb_connection, pixmap);
  2550. + bp_reply = xcb_dri3_buffer_from_pixmap_reply(xcb_connection, bp_cookie, NULL);
  2551. + if (!bp_reply)
  2552. + return FALSE;
  2553. + *fd = xcb_dri3_buffer_from_pixmap_reply_fds(xcb_connection, bp_reply)[0];
  2554. + *width = bp_reply->width;
  2555. + *height = bp_reply->height;
  2556. + *stride = bp_reply->stride;
  2557. + *depth = bp_reply->depth;
  2558. + *bpp = bp_reply->depth;
  2559. + return TRUE;
  2560. +}
  2561. +
  2562. +static PRESENTPixmapPriv *PRESENTFindPixmapPriv(PRESENTpriv *present_priv, uint32_t serial)
  2563. +{
  2564. + PRESENTPixmapPriv *current = present_priv->first_present_priv;
  2565. +
  2566. + while (current)
  2567. + {
  2568. + if (current->serial == serial)
  2569. + return current;
  2570. + current = current->next;
  2571. + }
  2572. + return NULL;
  2573. +}
  2574. +
  2575. +static void PRESENThandle_events(PRESENTpriv *present_priv, xcb_present_generic_event_t *ge)
  2576. +{
  2577. + PRESENTPixmapPriv *present_pixmap_priv = NULL;
  2578. +
  2579. + switch (ge->evtype)
  2580. + {
  2581. + case XCB_PRESENT_COMPLETE_NOTIFY:
  2582. + {
  2583. + xcb_present_complete_notify_event_t *ce = (void *) ge;
  2584. + if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC)
  2585. + {
  2586. + if (ce->serial)
  2587. + present_priv->notify_with_serial_pending = FALSE;
  2588. + free(ce);
  2589. + return;
  2590. + }
  2591. + present_pixmap_priv = PRESENTFindPixmapPriv(present_priv, ce->serial);
  2592. + if (!present_pixmap_priv || ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
  2593. + {
  2594. + ERR("FATAL ERROR: PRESENT handling failed\n");
  2595. + free(ce);
  2596. + return;
  2597. + }
  2598. + present_pixmap_priv->present_complete_pending--;
  2599. + switch (ce->mode)
  2600. + {
  2601. + case XCB_PRESENT_COMPLETE_MODE_FLIP:
  2602. + present_pixmap_priv->last_present_was_flip = TRUE;
  2603. + break;
  2604. + case XCB_PRESENT_COMPLETE_MODE_COPY:
  2605. + present_pixmap_priv->last_present_was_flip = FALSE;
  2606. + break;
  2607. + }
  2608. + present_priv->pixmap_present_pending--;
  2609. + present_priv->last_msc = ce->msc;
  2610. + break;
  2611. + }
  2612. + case XCB_PRESENT_EVENT_IDLE_NOTIFY:
  2613. + {
  2614. + xcb_present_idle_notify_event_t *ie = (void *) ge;
  2615. + present_pixmap_priv = PRESENTFindPixmapPriv(present_priv, ie->serial);
  2616. + if (!present_pixmap_priv || present_pixmap_priv->pixmap != ie->pixmap)
  2617. + {
  2618. + ERR("FATAL ERROR: PRESENT handling failed\n");
  2619. + free(ie);
  2620. + return;
  2621. + }
  2622. + present_pixmap_priv->released = TRUE;
  2623. + present_priv->idle_notify_since_last_check = TRUE;
  2624. + break;
  2625. + }
  2626. + }
  2627. + free(ge);
  2628. +}
  2629. +
  2630. +static void PRESENTflush_events(PRESENTpriv *present_priv, BOOL assert_no_other_thread_waiting)
  2631. +{
  2632. + xcb_generic_event_t *ev;
  2633. +
  2634. + if ((present_priv->xcb_wait && !assert_no_other_thread_waiting) || /* don't steal events to someone waiting */
  2635. + !present_priv->special_event)
  2636. + return;
  2637. +
  2638. + while ((ev = xcb_poll_for_special_event(present_priv->xcb_connection,
  2639. + present_priv->special_event)) != NULL)
  2640. + {
  2641. + PRESENThandle_events(present_priv, (void *) ev);
  2642. + }
  2643. +}
  2644. +
  2645. +static BOOL PRESENTwait_events(PRESENTpriv *present_priv, BOOL allow_other_threads)
  2646. +{
  2647. + xcb_generic_event_t *ev;
  2648. +
  2649. + if (allow_other_threads)
  2650. + {
  2651. + present_priv->xcb_wait = TRUE;
  2652. + EnterCriticalSection(&present_priv->mutex_xcb_wait);
  2653. + LeaveCriticalSection(&present_priv->mutex_present);
  2654. + }
  2655. + ev = xcb_wait_for_special_event(present_priv->xcb_connection, present_priv->special_event);
  2656. + if (allow_other_threads)
  2657. + {
  2658. + LeaveCriticalSection(&present_priv->mutex_xcb_wait);
  2659. + EnterCriticalSection(&present_priv->mutex_present);
  2660. + present_priv->xcb_wait = FALSE;
  2661. + }
  2662. + if (!ev)
  2663. + {
  2664. + ERR("FATAL error: xcb had an error\n");
  2665. + return FALSE;
  2666. + }
  2667. +
  2668. + PRESENThandle_events(present_priv, (void *) ev);
  2669. + return TRUE;
  2670. +}
  2671. +
  2672. +static struct xcb_connection_t *create_xcb_connection(Display *dpy)
  2673. +{
  2674. + int screen_num = DefaultScreen(dpy);
  2675. + xcb_connection_t *ret;
  2676. + xcb_xfixes_query_version_cookie_t cookie;
  2677. + xcb_xfixes_query_version_reply_t *rep;
  2678. +
  2679. + ret = xcb_connect(DisplayString(dpy), &screen_num);
  2680. + cookie = xcb_xfixes_query_version_unchecked(ret, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
  2681. + rep = xcb_xfixes_query_version_reply(ret, cookie, NULL);
  2682. + if (rep)
  2683. + free(rep);
  2684. + return ret;
  2685. +}
  2686. +
  2687. +BOOL PRESENTInit(Display *dpy, PRESENTpriv **present_priv)
  2688. +{
  2689. + *present_priv = (PRESENTpriv *) HeapAlloc(GetProcessHeap(),
  2690. + HEAP_ZERO_MEMORY, sizeof(PRESENTpriv));
  2691. +
  2692. + if (!*present_priv)
  2693. + return FALSE;
  2694. +
  2695. + (*present_priv)->xcb_connection = create_xcb_connection(dpy);
  2696. + (*present_priv)->xcb_connection_bis = create_xcb_connection(dpy);
  2697. +
  2698. + InitializeCriticalSection(&(*present_priv)->mutex_present);
  2699. + InitializeCriticalSection(&(*present_priv)->mutex_xcb_wait);
  2700. + return TRUE;
  2701. +}
  2702. +
  2703. +static void PRESENTForceReleases(PRESENTpriv *present_priv)
  2704. +{
  2705. + PRESENTPixmapPriv *current = NULL;
  2706. +
  2707. + if (!present_priv->window)
  2708. + return;
  2709. +
  2710. + /* There should be no other thread listening for events here.
  2711. + * This can happen when hDestWindowOverride changes without reset.
  2712. + * This case should never happen, but can happen in theory.*/
  2713. + if (present_priv->xcb_wait)
  2714. + {
  2715. + xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window, 0, 0, 0, 0);
  2716. + xcb_flush(present_priv->xcb_connection);
  2717. + EnterCriticalSection(&present_priv->mutex_xcb_wait);
  2718. + LeaveCriticalSection(&present_priv->mutex_xcb_wait);
  2719. + /* the problem here is that we don't have access to the event the other thread got.
  2720. + * It is either presented event, idle event or notify event.
  2721. + */
  2722. + while (present_priv->pixmap_present_pending >= 2)
  2723. + PRESENTwait_events(present_priv, FALSE);
  2724. + PRESENTflush_events(present_priv, TRUE);
  2725. + /* Remaining events to come can be a pair of present/idle,
  2726. + * or an idle, or nothing. To be sure we are after all pixmaps
  2727. + * have been presented, add an event to the queue that can only
  2728. + * be after the present event, then if we receive an event more,
  2729. + * we are sure all pixmaps were presented */
  2730. + present_priv->notify_with_serial_pending = TRUE;
  2731. + xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window,
  2732. + 1, present_priv->last_target + 5, 0, 0);
  2733. +
  2734. + xcb_flush(present_priv->xcb_connection);
  2735. + while (present_priv->notify_with_serial_pending)
  2736. + PRESENTwait_events(present_priv, FALSE);
  2737. + /* Now we are sure we are not expecting any new event */
  2738. + }
  2739. + else
  2740. + {
  2741. + while (present_priv->pixmap_present_pending) /* wait all sent pixmaps are presented */
  2742. + PRESENTwait_events(present_priv, FALSE);
  2743. + PRESENTflush_events(present_priv, TRUE); /* may be remaining idle event */
  2744. + /* Since idle events are send with the complete events when it is not flips,
  2745. + * we are not expecting any new event here */
  2746. + }
  2747. +
  2748. + current = present_priv->first_present_priv;
  2749. + while (current)
  2750. + {
  2751. + if (!current->released)
  2752. + {
  2753. + if (!current->last_present_was_flip && !present_priv->xcb_wait)
  2754. + {
  2755. + ERR("ERROR: a pixmap seems not released by PRESENT for no reason. Code bug.\n");
  2756. + }
  2757. + else
  2758. + {
  2759. + /* Present the same pixmap with a non-valid part to force the copy mode and the releases */
  2760. + xcb_xfixes_region_t valid, update;
  2761. + xcb_rectangle_t rect_update;
  2762. + rect_update.x = 0;
  2763. + rect_update.y = 0;
  2764. + rect_update.width = 8;
  2765. + rect_update.height = 1;
  2766. + valid = xcb_generate_id(present_priv->xcb_connection);
  2767. + update = xcb_generate_id(present_priv->xcb_connection);
  2768. + xcb_xfixes_create_region(present_priv->xcb_connection, valid, 1, &rect_update);
  2769. + xcb_xfixes_create_region(present_priv->xcb_connection, update, 1, &rect_update);
  2770. + /* here we know the pixmap has been presented. Thus if it is on screen,
  2771. + * the following request can only make it released by the server if it is not */
  2772. + xcb_present_pixmap(present_priv->xcb_connection, present_priv->window,
  2773. + current->pixmap, 0, valid, update, 0, 0, None, None,
  2774. + None, XCB_PRESENT_OPTION_COPY | XCB_PRESENT_OPTION_ASYNC, 0, 0, 0, 0, NULL);
  2775. + xcb_flush(present_priv->xcb_connection);
  2776. + PRESENTwait_events(present_priv, FALSE); /* by assumption this can only be idle event */
  2777. + PRESENTflush_events(present_priv, TRUE); /* Shoudln't be needed */
  2778. + }
  2779. + }
  2780. + current = current->next;
  2781. + }
  2782. + /* Now all pixmaps are released (possibility if xcb_wait is true that one is not aware yet),
  2783. + * and we don't expect any new Present event to come from Xserver */
  2784. +}
  2785. +
  2786. +static void PRESENTFreeXcbQueue(PRESENTpriv *present_priv)
  2787. +{
  2788. + if (present_priv->window)
  2789. + {
  2790. + xcb_unregister_for_special_event(present_priv->xcb_connection, present_priv->special_event);
  2791. + present_priv->last_msc = 0;
  2792. + present_priv->last_target = 0;
  2793. + present_priv->special_event = NULL;
  2794. + }
  2795. +}
  2796. +
  2797. +static BOOL PRESENTPrivChangeWindow(PRESENTpriv *present_priv, XID window)
  2798. +{
  2799. + xcb_void_cookie_t cookie;
  2800. + xcb_generic_error_t *error;
  2801. + xcb_present_event_t eid;
  2802. +
  2803. + PRESENTForceReleases(present_priv);
  2804. + PRESENTFreeXcbQueue(present_priv);
  2805. + present_priv->window = window;
  2806. +
  2807. + if (window)
  2808. + {
  2809. + cookie = xcb_present_select_input_checked(present_priv->xcb_connection,
  2810. + (eid = xcb_generate_id(present_priv->xcb_connection)), window,
  2811. + XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY | XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
  2812. +
  2813. + present_priv->special_event = xcb_register_for_special_xge(present_priv->xcb_connection,
  2814. + &xcb_present_id, eid, NULL);
  2815. +
  2816. + error = xcb_request_check(present_priv->xcb_connection, cookie); /* performs a flush */
  2817. + if (error || !present_priv->special_event)
  2818. + {
  2819. + ERR("FAILED to use the X PRESENT extension. Was the destination a window ?\n");
  2820. + if (present_priv->special_event)
  2821. + xcb_unregister_for_special_event(present_priv->xcb_connection, present_priv->special_event);
  2822. + present_priv->special_event = NULL;
  2823. + present_priv->window = 0;
  2824. + }
  2825. + }
  2826. + return (present_priv->window != 0);
  2827. +}
  2828. +
  2829. +/* Destroy the content, except the link and the struct mem */
  2830. +static void PRESENTDestroyPixmapContent(Display *dpy, PRESENTPixmapPriv *present_pixmap)
  2831. +{
  2832. + XFreePixmap(dpy, present_pixmap->pixmap);
  2833. +#ifdef D3D9NINE_DRI2
  2834. + if (present_pixmap->dri2_info.is_dri2)
  2835. + {
  2836. + struct DRI2priv *dri2_priv = present_pixmap->dri2_info.dri2_priv;
  2837. + EGLenum current_api;
  2838. + current_api = eglQueryAPI();
  2839. + eglBindAPI(EGL_OPENGL_API);
  2840. + if (eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context))
  2841. + {
  2842. + glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_read);
  2843. + glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_write);
  2844. + glDeleteTextures(1, &present_pixmap->dri2_info.texture_read);
  2845. + glDeleteTextures(1, &present_pixmap->dri2_info.texture_write);
  2846. + }
  2847. + else
  2848. + ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
  2849. +
  2850. + eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  2851. + eglBindAPI(current_api);
  2852. + }
  2853. +#endif
  2854. +}
  2855. +
  2856. +void PRESENTDestroy(Display *dpy, PRESENTpriv *present_priv)
  2857. +{
  2858. + PRESENTPixmapPriv *current = NULL;
  2859. +
  2860. + EnterCriticalSection(&present_priv->mutex_present);
  2861. +
  2862. + PRESENTForceReleases(present_priv);
  2863. +
  2864. + current = present_priv->first_present_priv;
  2865. + while (current)
  2866. + {
  2867. + PRESENTPixmapPriv *next = current->next;
  2868. + PRESENTDestroyPixmapContent(dpy, current);
  2869. + HeapFree(GetProcessHeap(), 0, current);
  2870. + current = next;
  2871. + }
  2872. +
  2873. + PRESENTFreeXcbQueue(present_priv);
  2874. +
  2875. + xcb_disconnect(present_priv->xcb_connection);
  2876. + xcb_disconnect(present_priv->xcb_connection_bis);
  2877. + LeaveCriticalSection(&present_priv->mutex_present);
  2878. + DeleteCriticalSection(&present_priv->mutex_present);
  2879. + DeleteCriticalSection(&present_priv->mutex_xcb_wait);
  2880. +
  2881. + HeapFree(GetProcessHeap(), 0, present_priv);
  2882. +}
  2883. +
  2884. +BOOL PRESENTPixmapInit(PRESENTpriv *present_priv, Pixmap pixmap, PRESENTPixmapPriv **present_pixmap_priv)
  2885. +{
  2886. + xcb_get_geometry_cookie_t cookie;
  2887. + xcb_get_geometry_reply_t *reply;
  2888. +
  2889. + cookie = xcb_get_geometry(present_priv->xcb_connection, pixmap);
  2890. + reply = xcb_get_geometry_reply(present_priv->xcb_connection, cookie, NULL);
  2891. +
  2892. + if (!reply)
  2893. + return FALSE;
  2894. +
  2895. + *present_pixmap_priv = (PRESENTPixmapPriv *) HeapAlloc(GetProcessHeap(),
  2896. + HEAP_ZERO_MEMORY, sizeof(PRESENTPixmapPriv));
  2897. +
  2898. + if (!*present_pixmap_priv)
  2899. + {
  2900. + free(reply);
  2901. + return FALSE;
  2902. + }
  2903. + EnterCriticalSection(&present_priv->mutex_present);
  2904. +
  2905. + (*present_pixmap_priv)->released = TRUE;
  2906. + (*present_pixmap_priv)->pixmap = pixmap;
  2907. + (*present_pixmap_priv)->present_priv = present_priv;
  2908. + (*present_pixmap_priv)->next = present_priv->first_present_priv;
  2909. + (*present_pixmap_priv)->width = reply->width;
  2910. + (*present_pixmap_priv)->height = reply->height;
  2911. + (*present_pixmap_priv)->depth = reply->depth;
  2912. +#ifdef D3D9NINE_DRI2
  2913. + (*present_pixmap_priv)->dri2_info.is_dri2 = FALSE;
  2914. +#endif
  2915. + free(reply);
  2916. +
  2917. + present_priv->last_serial_given++;
  2918. + (*present_pixmap_priv)->serial = present_priv->last_serial_given;
  2919. + present_priv->first_present_priv = *present_pixmap_priv;
  2920. +
  2921. + LeaveCriticalSection(&present_priv->mutex_present);
  2922. + return TRUE;
  2923. +}
  2924. +
  2925. +#ifdef D3D9NINE_DRI2
  2926. +
  2927. +BOOL DRI2FallbackPRESENTPixmap(PRESENTpriv *present_priv, struct DRI2priv *dri2_priv,
  2928. + int fd, int width, int height, int stride, int depth,
  2929. + int bpp, PRESENTPixmapPriv **present_pixmap_priv)
  2930. +{
  2931. + Window root = RootWindow(dri2_priv->dpy, DefaultScreen(dri2_priv->dpy));
  2932. + Pixmap pixmap;
  2933. + EGLImageKHR image;
  2934. + GLuint texture_read, texture_write, fbo_read, fbo_write;
  2935. + EGLint attribs[] = {
  2936. + EGL_WIDTH, 0,
  2937. + EGL_HEIGHT, 0,
  2938. + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,
  2939. + EGL_DMA_BUF_PLANE0_FD_EXT, 0,
  2940. + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
  2941. + EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
  2942. + EGL_NONE
  2943. + };
  2944. + EGLenum current_api = 0;
  2945. + int status;
  2946. +
  2947. + EnterCriticalSection(&present_priv->mutex_present);
  2948. +
  2949. + pixmap = XCreatePixmap(dri2_priv->dpy, root, width, height, 24);
  2950. + if (!pixmap)
  2951. + goto fail;
  2952. +
  2953. + attribs[1] = width;
  2954. + attribs[3] = height;
  2955. + attribs[7] = fd;
  2956. + attribs[11] = stride;
  2957. +
  2958. + current_api = eglQueryAPI();
  2959. + eglBindAPI(EGL_OPENGL_API);
  2960. +
  2961. + /* We bind the dma-buf to a EGLImage, then to a texture, and then to a fbo.
  2962. + * Note that we can delete the EGLImage, but we shouldn't delete the texture,
  2963. + * else the fbo is invalid */
  2964. +
  2965. + image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display,
  2966. + EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
  2967. +
  2968. + if (image == EGL_NO_IMAGE_KHR)
  2969. + goto fail;
  2970. + close(fd);
  2971. +
  2972. + if (eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context))
  2973. + {
  2974. + glGenTextures(1, &texture_read);
  2975. + glBindTexture(GL_TEXTURE_2D, texture_read);
  2976. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  2977. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  2978. + dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image);
  2979. + glGenFramebuffers(1, &fbo_read);
  2980. + glBindFramebuffer(GL_FRAMEBUFFER, fbo_read);
  2981. + glFramebufferTexture2D(GL_FRAMEBUFFER,
  2982. + GL_COLOR_ATTACHMENT0,
  2983. + GL_TEXTURE_2D, texture_read,
  2984. + 0);
  2985. + status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  2986. + if (status != GL_FRAMEBUFFER_COMPLETE)
  2987. + goto fail;
  2988. + glBindTexture(GL_TEXTURE_2D, 0);
  2989. + dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image);
  2990. +
  2991. + /* We bind a newly created pixmap (to which we want to copy the content)
  2992. + * to an EGLImage, then to a texture, then to a fbo. */
  2993. + image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display,
  2994. + dri2_priv->context,
  2995. + EGL_NATIVE_PIXMAP_KHR,
  2996. + (void *)pixmap, NULL);
  2997. + if (image == EGL_NO_IMAGE_KHR)
  2998. + goto fail;
  2999. +
  3000. + glGenTextures(1, &texture_write);
  3001. + glBindTexture(GL_TEXTURE_2D, texture_write);
  3002. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  3003. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  3004. + dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image);
  3005. + glGenFramebuffers(1, &fbo_write);
  3006. + glBindFramebuffer(GL_FRAMEBUFFER, fbo_write);
  3007. + glFramebufferTexture2D(GL_FRAMEBUFFER,
  3008. + GL_COLOR_ATTACHMENT0,
  3009. + GL_TEXTURE_2D, texture_write,
  3010. + 0);
  3011. + status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  3012. + if (status != GL_FRAMEBUFFER_COMPLETE)
  3013. + goto fail;
  3014. + glBindTexture(GL_TEXTURE_2D, 0);
  3015. + dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image);
  3016. + }
  3017. + else
  3018. + ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
  3019. +
  3020. + eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  3021. +
  3022. + *present_pixmap_priv = (PRESENTPixmapPriv *) HeapAlloc(GetProcessHeap(),
  3023. + HEAP_ZERO_MEMORY, sizeof(PRESENTPixmapPriv));
  3024. +
  3025. + if (!*present_pixmap_priv)
  3026. + goto fail;
  3027. +
  3028. + (*present_pixmap_priv)->released = TRUE;
  3029. + (*present_pixmap_priv)->pixmap = pixmap;
  3030. + (*present_pixmap_priv)->present_priv = present_priv;
  3031. + (*present_pixmap_priv)->next = present_priv->first_present_priv;
  3032. + (*present_pixmap_priv)->width = width;
  3033. + (*present_pixmap_priv)->height = height;
  3034. + (*present_pixmap_priv)->depth = depth;
  3035. + (*present_pixmap_priv)->dri2_info.is_dri2 = TRUE;
  3036. + (*present_pixmap_priv)->dri2_info.dri2_priv = dri2_priv;
  3037. + (*present_pixmap_priv)->dri2_info.fbo_read = fbo_read;
  3038. + (*present_pixmap_priv)->dri2_info.fbo_write = fbo_write;
  3039. + (*present_pixmap_priv)->dri2_info.texture_read = texture_read;
  3040. + (*present_pixmap_priv)->dri2_info.texture_write = texture_write;
  3041. +
  3042. + present_priv->last_serial_given++;
  3043. + (*present_pixmap_priv)->serial = present_priv->last_serial_given;
  3044. + present_priv->first_present_priv = *present_pixmap_priv;
  3045. +
  3046. + eglBindAPI(current_api);
  3047. +
  3048. + LeaveCriticalSection(&present_priv->mutex_present);
  3049. + return TRUE;
  3050. +fail:
  3051. + eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  3052. + eglBindAPI(current_api);
  3053. + LeaveCriticalSection(&present_priv->mutex_present);
  3054. + return FALSE;
  3055. +}
  3056. +
  3057. +#endif
  3058. +
  3059. +BOOL PRESENTTryFreePixmap(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv)
  3060. +{
  3061. + PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
  3062. + PRESENTPixmapPriv *current;
  3063. +
  3064. + EnterCriticalSection(&present_priv->mutex_present);
  3065. +
  3066. + if (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending)
  3067. + {
  3068. + LeaveCriticalSection(&present_priv->mutex_present);
  3069. + return FALSE;
  3070. + }
  3071. +
  3072. + if (present_priv->first_present_priv == present_pixmap_priv)
  3073. + {
  3074. + present_priv->first_present_priv = present_pixmap_priv->next;
  3075. + goto free_priv;
  3076. + }
  3077. +
  3078. + current = present_priv->first_present_priv;
  3079. + while (current->next != present_pixmap_priv)
  3080. + current = current->next;
  3081. + current->next = present_pixmap_priv->next;
  3082. +free_priv:
  3083. + PRESENTDestroyPixmapContent(dpy, present_pixmap_priv);
  3084. + HeapFree(GetProcessHeap(), 0, present_pixmap_priv);
  3085. + LeaveCriticalSection(&present_priv->mutex_present);
  3086. + return TRUE;
  3087. +}
  3088. +
  3089. +BOOL PRESENTHelperCopyFront(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv)
  3090. +{
  3091. + PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
  3092. + xcb_void_cookie_t cookie;
  3093. + xcb_generic_error_t *error;
  3094. + uint32_t v = 0;
  3095. + xcb_gcontext_t gc;
  3096. +
  3097. + EnterCriticalSection(&present_priv->mutex_present);
  3098. +
  3099. + if (!present_priv->window)
  3100. + {
  3101. + LeaveCriticalSection(&present_priv->mutex_present);
  3102. + return FALSE;
  3103. + }
  3104. +
  3105. + gc = xcb_generate_id(present_priv->xcb_connection);
  3106. + xcb_create_gc(present_priv->xcb_connection, gc, present_priv->window,
  3107. + XCB_GC_GRAPHICS_EXPOSURES, &v);
  3108. +
  3109. + cookie = xcb_copy_area_checked(present_priv->xcb_connection,
  3110. + present_priv->window, present_pixmap_priv->pixmap, gc,
  3111. + 0, 0, 0, 0, present_pixmap_priv->width, present_pixmap_priv->height);
  3112. +
  3113. + error = xcb_request_check(present_priv->xcb_connection, cookie);
  3114. + xcb_free_gc(present_priv->xcb_connection, gc);
  3115. + LeaveCriticalSection(&present_priv->mutex_present);
  3116. + return (error != NULL);
  3117. +}
  3118. +
  3119. +BOOL PRESENTPixmap(Display *dpy, XID window, PRESENTPixmapPriv *present_pixmap_priv,
  3120. + const UINT PresentationInterval, const BOOL PresentAsync, const BOOL SwapEffectCopy,
  3121. + const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion)
  3122. +{
  3123. + PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
  3124. +#ifdef D3D9NINE_DRI2
  3125. + struct DRI2priv *dri2_priv = present_pixmap_priv->dri2_info.dri2_priv;
  3126. + EGLenum current_api = 0;
  3127. +#endif
  3128. + xcb_void_cookie_t cookie;
  3129. + xcb_generic_error_t *error;
  3130. + int64_t target_msc, presentationInterval;
  3131. + xcb_xfixes_region_t valid, update;
  3132. + int16_t x_off, y_off;
  3133. + uint32_t options = XCB_PRESENT_OPTION_NONE;
  3134. +
  3135. + EnterCriticalSection(&present_priv->mutex_present);
  3136. +
  3137. + if (window != present_priv->window)
  3138. + PRESENTPrivChangeWindow(present_priv, window);
  3139. +
  3140. + if (!window)
  3141. + {
  3142. + ERR("ERROR: Try to Present a pixmap on a NULL window\n");
  3143. + LeaveCriticalSection(&present_priv->mutex_present);
  3144. + return FALSE;
  3145. + }
  3146. +
  3147. + PRESENTflush_events(present_priv, FALSE);
  3148. + /* Note: present_pixmap_priv->present_complete_pending may be non-0, because
  3149. + * on some paths the Xserver sends the complete event just after the idle
  3150. + * event. */
  3151. + if (!present_pixmap_priv->released)
  3152. + {
  3153. + ERR("FATAL ERROR: Trying to Present a pixmap not released\n");
  3154. + LeaveCriticalSection(&present_priv->mutex_present);
  3155. + return FALSE;
  3156. + }
  3157. +#ifdef D3D9NINE_DRI2
  3158. + if (present_pixmap_priv->dri2_info.is_dri2)
  3159. + {
  3160. + current_api = eglQueryAPI();
  3161. + eglBindAPI(EGL_OPENGL_API);
  3162. + if (eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context))
  3163. + {
  3164. + glBindFramebuffer(GL_READ_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_read);
  3165. + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_write);
  3166. +
  3167. + glBlitFramebuffer(0, 0, present_pixmap_priv->width, present_pixmap_priv->height,
  3168. + 0, 0, present_pixmap_priv->width, present_pixmap_priv->height,
  3169. + GL_COLOR_BUFFER_BIT, GL_NEAREST);
  3170. + glFlush(); /* Perhaps useless */
  3171. + }
  3172. + else
  3173. + ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
  3174. +
  3175. + eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  3176. + eglBindAPI(current_api);
  3177. + }
  3178. +#endif
  3179. + target_msc = present_priv->last_msc;
  3180. +
  3181. + presentationInterval = PresentationInterval;
  3182. + if (PresentAsync)
  3183. + options |= XCB_PRESENT_OPTION_ASYNC;
  3184. + if (SwapEffectCopy)
  3185. + options |= XCB_PRESENT_OPTION_COPY;
  3186. +
  3187. + target_msc += presentationInterval * (present_priv->pixmap_present_pending + 1);
  3188. +
  3189. + /* Note: PRESENT defines some way to do partial copy:
  3190. + * presentproto:
  3191. + * 'x-off' and 'y-off' define the location in the window where
  3192. + * the 0,0 location of the pixmap will be presented. valid-area
  3193. + * and update-area are relative to the pixmap.
  3194. + */
  3195. + if (!pSourceRect && !pDestRect && !pDirtyRegion)
  3196. + {
  3197. + valid = 0;
  3198. + update = 0;
  3199. + x_off = 0;
  3200. + y_off = 0;
  3201. + }
  3202. + else
  3203. + {
  3204. + xcb_rectangle_t rect_update;
  3205. + xcb_rectangle_t *rect_updates;
  3206. + int i;
  3207. +
  3208. + rect_update.x = 0;
  3209. + rect_update.y = 0;
  3210. + rect_update.width = present_pixmap_priv->width;
  3211. + rect_update.height = present_pixmap_priv->height;
  3212. + x_off = 0;
  3213. + y_off = 0;
  3214. + if (pSourceRect)
  3215. + {
  3216. + x_off = -pSourceRect->left;
  3217. + y_off = -pSourceRect->top;
  3218. + rect_update.x = pSourceRect->left;
  3219. + rect_update.y = pSourceRect->top;
  3220. + rect_update.width = pSourceRect->right - pSourceRect->left;
  3221. + rect_update.height = pSourceRect->bottom - pSourceRect->top;
  3222. + }
  3223. + if (pDestRect)
  3224. + {
  3225. + x_off += pDestRect->left;
  3226. + y_off += pDestRect->top;
  3227. + rect_update.width = pDestRect->right - pDestRect->left;
  3228. + rect_update.height = pDestRect->bottom - pDestRect->top;
  3229. + /* Note: the size of pDestRect and pSourceRect are supposed to be the same size
  3230. + * because the driver would have done things to assure that. */
  3231. + }
  3232. + valid = xcb_generate_id(present_priv->xcb_connection_bis);
  3233. + update = xcb_generate_id(present_priv->xcb_connection_bis);
  3234. + xcb_xfixes_create_region(present_priv->xcb_connection_bis, valid, 1, &rect_update);
  3235. + if (pDirtyRegion && pDirtyRegion->rdh.nCount)
  3236. + {
  3237. + rect_updates = (void *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  3238. + sizeof(xcb_rectangle_t) * pDirtyRegion->rdh.nCount);
  3239. +
  3240. + for (i = 0; i < pDirtyRegion->rdh.nCount; i++)
  3241. + {
  3242. + RECT rc;
  3243. + memcpy(&rc, pDirtyRegion->Buffer + i * sizeof(RECT), sizeof(RECT));
  3244. + rect_update.x = rc.left;
  3245. + rect_update.y = rc.top;
  3246. + rect_update.width = rc.right - rc.left;
  3247. + rect_update.height = rc.bottom - rc.top;
  3248. + memcpy(rect_updates + i * sizeof(xcb_rectangle_t), &rect_update, sizeof(xcb_rectangle_t));
  3249. + }
  3250. + xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, pDirtyRegion->rdh.nCount, rect_updates);
  3251. + HeapFree(GetProcessHeap(), 0, rect_updates);
  3252. + } else
  3253. + xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, 1, &rect_update);
  3254. + }
  3255. +
  3256. + cookie = xcb_present_pixmap_checked(present_priv->xcb_connection_bis,
  3257. + window, present_pixmap_priv->pixmap, present_pixmap_priv->serial,
  3258. + valid, update, x_off, y_off, None, None, None, options,
  3259. + target_msc, 0, 0, 0, NULL);
  3260. + error = xcb_request_check(present_priv->xcb_connection_bis, cookie); /* performs a flush */
  3261. +
  3262. + if (update)
  3263. + xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, update);
  3264. + if (valid)
  3265. + xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, valid);
  3266. +
  3267. + if (error)
  3268. + {
  3269. + xcb_get_geometry_cookie_t cookie_geom;
  3270. + xcb_get_geometry_reply_t *reply;
  3271. +
  3272. + cookie_geom = xcb_get_geometry(present_priv->xcb_connection_bis, window);
  3273. + reply = xcb_get_geometry_reply(present_priv->xcb_connection_bis, cookie_geom, NULL);
  3274. +
  3275. + ERR("Error using PRESENT. Here some debug info\n");
  3276. + if (!reply)
  3277. + {
  3278. + ERR("Error querying window info. Perhaps it doesn't exist anymore\n");
  3279. + LeaveCriticalSection(&present_priv->mutex_present);
  3280. + return FALSE;
  3281. + }
  3282. + ERR("Pixmap: width=%d, height=%d, depth=%d\n",
  3283. + present_pixmap_priv->width, present_pixmap_priv->height,
  3284. + present_pixmap_priv->depth);
  3285. +
  3286. + ERR("Window: width=%d, height=%d, depth=%d, x=%d, y=%d\n",
  3287. + (int) reply->width, (int) reply->height,
  3288. + (int) reply->depth, (int) reply->x, (int) reply->y);
  3289. +
  3290. + ERR("Present parameter: PresentationInterval=%d, Pending presentations=%d\n",
  3291. + PresentationInterval, present_priv->pixmap_present_pending);
  3292. +
  3293. + if (present_pixmap_priv->depth != reply->depth)
  3294. + ERR("Depths are different. PRESENT needs the pixmap and the window have same depth\n");
  3295. + free(reply);
  3296. + LeaveCriticalSection(&present_priv->mutex_present);
  3297. + return FALSE;
  3298. + }
  3299. + present_priv->last_target = target_msc;
  3300. + present_priv->pixmap_present_pending++;
  3301. + present_pixmap_priv->present_complete_pending++;
  3302. + present_pixmap_priv->released = FALSE;
  3303. + LeaveCriticalSection(&present_priv->mutex_present);
  3304. + return TRUE;
  3305. +}
  3306. +
  3307. +BOOL PRESENTWaitPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv)
  3308. +{
  3309. + PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
  3310. +
  3311. + EnterCriticalSection(&present_priv->mutex_present);
  3312. +
  3313. + PRESENTflush_events(present_priv, FALSE);
  3314. +
  3315. + /* The part with present_pixmap_priv->present_complete_pending is legacy behaviour.
  3316. + * It matters for SwapEffectCopy with swapinterval > 0. */
  3317. + while (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending)
  3318. + {
  3319. + /* Note: following if should not happen because we'll never
  3320. + * use two PRESENTWaitPixmapReleased in parallels on same window.
  3321. + * However it would make it work in that case */
  3322. + if (present_priv->xcb_wait)
  3323. + {
  3324. + /* we allow only one thread to dispatch events */
  3325. + EnterCriticalSection(&present_priv->mutex_xcb_wait);
  3326. + /* here the other thread got an event but hasn't treated it yet */
  3327. + LeaveCriticalSection(&present_priv->mutex_xcb_wait);
  3328. + LeaveCriticalSection(&present_priv->mutex_present);
  3329. + Sleep(10); /* Let it treat the event */
  3330. + EnterCriticalSection(&present_priv->mutex_present);
  3331. + }
  3332. + else if (!PRESENTwait_events(present_priv, TRUE))
  3333. + {
  3334. + LeaveCriticalSection(&present_priv->mutex_present);
  3335. + return FALSE;
  3336. + }
  3337. + }
  3338. + LeaveCriticalSection(&present_priv->mutex_present);
  3339. + return TRUE;
  3340. +}
  3341. +
  3342. +BOOL PRESENTIsPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv)
  3343. +{
  3344. + PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
  3345. + BOOL ret;
  3346. +
  3347. + EnterCriticalSection(&present_priv->mutex_present);
  3348. +
  3349. + PRESENTflush_events(present_priv, FALSE);
  3350. +
  3351. + ret = present_pixmap_priv->released;
  3352. +
  3353. + LeaveCriticalSection(&present_priv->mutex_present);
  3354. + return ret;
  3355. +}
  3356. +
  3357. +BOOL PRESENTWaitReleaseEvent(PRESENTpriv *present_priv)
  3358. +{
  3359. +
  3360. + EnterCriticalSection(&present_priv->mutex_present);
  3361. +
  3362. + while (!present_priv->idle_notify_since_last_check)
  3363. + {
  3364. + /* Note: following if should not happen because we'll never
  3365. + * use two PRESENTWaitPixmapReleased in parallels on same window.
  3366. + * However it would make it work in that case */
  3367. + if (present_priv->xcb_wait)
  3368. + {
  3369. + /* we allow only one thread to dispatch events */
  3370. + EnterCriticalSection(&present_priv->mutex_xcb_wait);
  3371. + /* here the other thread got an event but hasn't treated it yet */
  3372. + LeaveCriticalSection(&present_priv->mutex_xcb_wait);
  3373. + LeaveCriticalSection(&present_priv->mutex_present);
  3374. + Sleep(10); /* Let it treat the event */
  3375. + EnterCriticalSection(&present_priv->mutex_present);
  3376. + }
  3377. + else if (!PRESENTwait_events(present_priv, TRUE))
  3378. + {
  3379. + ERR("Issue in PRESENTWaitReleaseEvent\n");
  3380. + LeaveCriticalSection(&present_priv->mutex_present);
  3381. + return FALSE;
  3382. + }
  3383. + }
  3384. + present_priv->idle_notify_since_last_check = FALSE;
  3385. +
  3386. + LeaveCriticalSection(&present_priv->mutex_present);
  3387. + return TRUE;
  3388. +}
  3389. diff --git a/dlls/d3d9-nine/dri3.h b/dlls/d3d9-nine/dri3.h
  3390. new file mode 100644
  3391. index 0000000000..3c9309dedb
  3392. --- /dev/null
  3393. +++ b/dlls/d3d9-nine/dri3.h
  3394. @@ -0,0 +1,91 @@
  3395. +/*
  3396. + * Wine X11DRV DRI3 interface
  3397. + *
  3398. + * Copyright 2014 Axel Davy
  3399. + *
  3400. + * This library is free software; you can redistribute it and/or
  3401. + * modify it under the terms of the GNU Lesser General Public
  3402. + * License as published by the Free Software Foundation; either
  3403. + * version 2.1 of the License, or (at your option) any later version.
  3404. + *
  3405. + * This library is distributed in the hope that it will be useful,
  3406. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3407. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  3408. + * Lesser General Public License for more details.
  3409. + *
  3410. + * You should have received a copy of the GNU Lesser General Public
  3411. + * License along with this library; if not, write to the Free Software
  3412. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  3413. + */
  3414. +
  3415. +#ifndef __WINE_DRI3_H
  3416. +#define __WINE_DRI3_H
  3417. +
  3418. +#ifndef __WINE_CONFIG_H
  3419. +# error You must include config.h to use this header
  3420. +#endif
  3421. +
  3422. +#include <X11/Xlib.h>
  3423. +#include <wingdi.h>
  3424. +
  3425. +BOOL DRI3CheckExtension(Display *dpy, int major, int minor);
  3426. +
  3427. +#ifdef D3D9NINE_DRI2
  3428. +struct DRI2priv;
  3429. +
  3430. +BOOL DRI2FallbackInit(Display *dpy, struct DRI2priv **priv);
  3431. +
  3432. +void DRI2FallbackDestroy(struct DRI2priv *priv);
  3433. +
  3434. +BOOL DRI2FallbackCheckSupport(Display *dpy);
  3435. +#endif
  3436. +
  3437. +BOOL PRESENTCheckExtension(Display *dpy, int major, int minor);
  3438. +
  3439. +BOOL DRI3Open(Display *dpy, int screen, int *device_fd);
  3440. +
  3441. +#ifdef D3D9NINE_DRI2
  3442. +BOOL DRI2FallbackOpen(Display *dpy, int screen, int *device_fd);
  3443. +#endif
  3444. +
  3445. +BOOL DRI3PixmapFromDmaBuf(Display *dpy, int screen, int fd, int width, int height,
  3446. + int stride, int depth, int bpp, Pixmap *pixmap);
  3447. +
  3448. +BOOL DRI3DmaBufFromPixmap(Display *dpy, Pixmap pixmap, int *fd, int *width, int *height,
  3449. + int *stride, int *depth, int *bpp);
  3450. +
  3451. +typedef struct PRESENTPriv PRESENTpriv;
  3452. +typedef struct PRESENTPixmapPriv PRESENTPixmapPriv;
  3453. +
  3454. +BOOL PRESENTInit(Display *dpy, PRESENTpriv **present_priv);
  3455. +
  3456. +/* will clean properly and free all PRESENTPixmapPriv associated to PRESENTpriv.
  3457. + * PRESENTPixmapPriv should not be freed by something else.
  3458. + * If never a PRESENTPixmapPriv has to be destroyed,
  3459. + * please destroy the current PRESENTpriv and create a new one.
  3460. + * This will take care than all pixmaps are released */
  3461. +void PRESENTDestroy(Display *dpy, PRESENTpriv *present_priv);
  3462. +
  3463. +BOOL PRESENTPixmapInit(PRESENTpriv *present_priv, Pixmap pixmap, PRESENTPixmapPriv **present_pixmap_priv);
  3464. +
  3465. +#ifdef D3D9NINE_DRI2
  3466. +BOOL DRI2FallbackPRESENTPixmap(PRESENTpriv *present_priv, struct DRI2priv *priv,
  3467. + int fd, int width, int height, int stride, int depth,
  3468. + int bpp, PRESENTPixmapPriv **present_pixmap_priv);
  3469. +#endif
  3470. +
  3471. +BOOL PRESENTTryFreePixmap(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv);
  3472. +
  3473. +BOOL PRESENTHelperCopyFront(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv);
  3474. +
  3475. +BOOL PRESENTPixmap(Display *dpy, XID window, PRESENTPixmapPriv *present_pixmap_priv,
  3476. + const UINT PresentationInterval, const BOOL PresentAsync, const BOOL SwapEffectCopy,
  3477. + const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion);
  3478. +
  3479. +BOOL PRESENTWaitPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv);
  3480. +
  3481. +BOOL PRESENTIsPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv);
  3482. +
  3483. +BOOL PRESENTWaitReleaseEvent(PRESENTpriv *present_priv);
  3484. +
  3485. +#endif /* __WINE_DRI3_H */
  3486. diff --git a/dlls/d3d9-nine/present.c b/dlls/d3d9-nine/present.c
  3487. new file mode 100644
  3488. index 0000000000..2d9390a358
  3489. --- /dev/null
  3490. +++ b/dlls/d3d9-nine/present.c
  3491. @@ -0,0 +1,1748 @@
  3492. +/*
  3493. + * Wine ID3DAdapter9 support functions
  3494. + *
  3495. + * Copyright 2013 Joakim Sindholt
  3496. + * Christoph Bumiller
  3497. + * Copyright 2014 Tiziano Bacocco
  3498. + * David Heidelberger
  3499. + * Copyright 2014-2015 Axel Davy
  3500. + * Copyright 2015 Patrick Rudolph
  3501. + *
  3502. + * This library is free software; you can redistribute it and/or
  3503. + * modify it under the terms of the GNU Lesser General Public
  3504. + * License as published by the Free Software Foundation; either
  3505. + * version 2.1 of the License, or (at your option) any later version.
  3506. + *
  3507. + * This library is distributed in the hope that it will be useful,
  3508. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3509. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  3510. + * Lesser General Public License for more details.
  3511. + *
  3512. + * You should have received a copy of the GNU Lesser General Public
  3513. + * License along with this library; if not, write to the Free Software
  3514. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  3515. + */
  3516. +
  3517. +#include "config.h"
  3518. +#include "wine/port.h"
  3519. +#include "wine/debug.h"
  3520. +
  3521. +WINE_DEFAULT_DEBUG_CHANNEL(d3d9nine);
  3522. +
  3523. +#include <d3dadapter/drm.h>
  3524. +#include <X11/Xutil.h>
  3525. +
  3526. +#include "dri3.h"
  3527. +#include "wndproc.h"
  3528. +
  3529. +#include "wine/library.h" // for wine_dl*
  3530. +#include "wine/unicode.h" // for strcpyW
  3531. +
  3532. +#ifndef D3DPRESENT_DONOTWAIT
  3533. +#define D3DPRESENT_DONOTWAIT 0x00000001
  3534. +#endif
  3535. +
  3536. +#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MAJOR 1
  3537. +#if defined (ID3DPresent_SetPresentParameters2)
  3538. +#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 3
  3539. +#elif defined (ID3DPresent_ResolutionMismatch)
  3540. +#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 2
  3541. +#elif defined (ID3DPresent_GetWindowOccluded)
  3542. +#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 1
  3543. +#else
  3544. +#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 0
  3545. +#endif
  3546. +
  3547. +static const struct D3DAdapter9DRM *d3d9_drm = NULL;
  3548. +#ifdef D3D9NINE_DRI2
  3549. +static int is_dri2_fallback = 0;
  3550. +#endif
  3551. +
  3552. +/* Start section of x11drv.h */
  3553. +#define X11DRV_ESCAPE 6789
  3554. +enum x11drv_escape_codes
  3555. +{
  3556. + X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
  3557. + X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
  3558. + X11DRV_START_EXPOSURES, /* start graphics exposures */
  3559. + X11DRV_END_EXPOSURES, /* end graphics exposures */
  3560. + X11DRV_FLUSH_GL_DRAWABLE /* flush changes made to the gl drawable */
  3561. +};
  3562. +
  3563. +struct x11drv_escape_get_drawable
  3564. +{
  3565. + enum x11drv_escape_codes code; /* escape code (X11DRV_GET_DRAWABLE) */
  3566. + Drawable drawable; /* X drawable */
  3567. + Drawable gl_drawable; /* GL drawable */
  3568. + int pixel_format; /* internal GL pixel format */
  3569. +};
  3570. +/* End section x11drv.h */
  3571. +
  3572. +static XContext d3d_hwnd_context;
  3573. +static CRITICAL_SECTION context_section;
  3574. +static CRITICAL_SECTION_DEBUG critsect_debug =
  3575. +{
  3576. + 0, 0, &context_section,
  3577. + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
  3578. + 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
  3579. +};
  3580. +static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
  3581. +
  3582. +const GUID IID_ID3DPresent = { 0x77D60E80, 0xF1E6, 0x11DF, { 0x9E, 0x39, 0x95, 0x0C, 0xDF, 0xD7, 0x20, 0x85 } };
  3583. +const GUID IID_ID3DPresentGroup = { 0xB9C3016E, 0xF32A, 0x11DF, { 0x9C, 0x18, 0x92, 0xEA, 0xDE, 0xD7, 0x20, 0x85 } };
  3584. +
  3585. +struct d3d_drawable
  3586. +{
  3587. + Drawable drawable; /* X11 drawable */
  3588. + HDC hdc;
  3589. + HWND wnd; /* HWND (for convenience) */
  3590. +};
  3591. +
  3592. +struct DRI3Present
  3593. +{
  3594. + /* COM vtable */
  3595. + void *vtable;
  3596. + /* IUnknown reference count */
  3597. + LONG refs;
  3598. +
  3599. + D3DPRESENT_PARAMETERS params;
  3600. + HWND focus_wnd;
  3601. + PRESENTpriv *present_priv;
  3602. +#ifdef D3D9NINE_DRI2
  3603. + struct DRI2priv *dri2_priv;
  3604. +#endif
  3605. +
  3606. + WCHAR devname[32];
  3607. + HCURSOR hCursor;
  3608. +
  3609. + DEVMODEW initial_mode;
  3610. +
  3611. + DWORD style;
  3612. + DWORD style_ex;
  3613. +
  3614. + BOOL reapply_mode;
  3615. + BOOL ex;
  3616. + BOOL resolution_mismatch;
  3617. + BOOL occluded;
  3618. + BOOL drop_wnd_messages;
  3619. + BOOL no_window_changes;
  3620. + Display *gdi_display;
  3621. +
  3622. + UINT present_interval;
  3623. + BOOL present_async;
  3624. + BOOL present_swapeffectcopy;
  3625. + BOOL allow_discard_delayed_release;
  3626. + BOOL tear_free_discard;
  3627. + struct d3d_drawable *d3d;
  3628. +};
  3629. +
  3630. +struct D3DWindowBuffer
  3631. +{
  3632. + PRESENTPixmapPriv *present_pixmap_priv;
  3633. +};
  3634. +
  3635. +static void free_d3dadapter_drawable(struct d3d_drawable *d3d)
  3636. +{
  3637. + ReleaseDC(d3d->wnd, d3d->hdc);
  3638. + HeapFree(GetProcessHeap(), 0, d3d);
  3639. +}
  3640. +
  3641. +static void destroy_d3dadapter_drawable(Display *gdi_display, HWND hwnd)
  3642. +{
  3643. + struct d3d_drawable *d3d;
  3644. +
  3645. + EnterCriticalSection(&context_section);
  3646. + if (!XFindContext(gdi_display, (XID)hwnd,
  3647. + d3d_hwnd_context, (char **)&d3d))
  3648. + {
  3649. + XDeleteContext(gdi_display, (XID)hwnd, d3d_hwnd_context);
  3650. + free_d3dadapter_drawable(d3d);
  3651. + }
  3652. + LeaveCriticalSection(&context_section);
  3653. +}
  3654. +
  3655. +static RECT DRI3Present_GetClientRecWindowRelative(HWND hwnd)
  3656. +{
  3657. + RECT rect;
  3658. + RECT wnd;
  3659. +
  3660. + /* Get client space dimensions */
  3661. + GetClientRect(hwnd, &rect);
  3662. +
  3663. + /* Get window in screen space */
  3664. + GetWindowRect(hwnd, &wnd);
  3665. +
  3666. + /* Transform to offset */
  3667. + MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT) &wnd, 2);
  3668. + wnd.top *= -1;
  3669. + wnd.left *= -1;
  3670. + wnd.bottom = wnd.top + rect.bottom;
  3671. + wnd.right = wnd.left + rect.right;
  3672. +
  3673. + return wnd;
  3674. +}
  3675. +
  3676. +static struct d3d_drawable *create_d3dadapter_drawable(HWND hwnd)
  3677. +{
  3678. + struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
  3679. + struct d3d_drawable *d3d;
  3680. +
  3681. + d3d = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d));
  3682. + if (!d3d)
  3683. + {
  3684. + ERR("Couldn't allocate d3d_drawable.\n");
  3685. + return NULL;
  3686. + }
  3687. +
  3688. + d3d->hdc = GetDCEx(hwnd, 0, DCX_CACHE | DCX_CLIPSIBLINGS);
  3689. + if (ExtEscape(d3d->hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
  3690. + sizeof(extesc), (LPSTR)&extesc) <= 0)
  3691. + {
  3692. + ERR("Unexpected error in X Drawable lookup (hwnd=%p, hdc=%p)\n", hwnd, d3d->hdc);
  3693. + ReleaseDC(hwnd, d3d->hdc);
  3694. + HeapFree(GetProcessHeap(), 0, d3d);
  3695. + return NULL;
  3696. + }
  3697. +
  3698. + d3d->drawable = extesc.drawable;
  3699. + d3d->wnd = hwnd;
  3700. +
  3701. + return d3d;
  3702. +}
  3703. +
  3704. +static struct d3d_drawable *get_d3d_drawable(Display *gdi_display, HWND hwnd)
  3705. +{
  3706. + struct d3d_drawable *d3d, *race;
  3707. +
  3708. + EnterCriticalSection(&context_section);
  3709. + if (!XFindContext(gdi_display, (XID)hwnd, d3d_hwnd_context, (char **)&d3d))
  3710. + {
  3711. + return d3d;
  3712. + }
  3713. + LeaveCriticalSection(&context_section);
  3714. +
  3715. + TRACE("No d3d_drawable attached to hwnd %p, creating one.\n", hwnd);
  3716. +
  3717. + d3d = create_d3dadapter_drawable(hwnd);
  3718. + if (!d3d)
  3719. + return NULL;
  3720. +
  3721. + EnterCriticalSection(&context_section);
  3722. + if (!XFindContext(gdi_display, (XID)hwnd,
  3723. + d3d_hwnd_context, (char **)&race))
  3724. + {
  3725. + /* apparently someone beat us to creating this d3d drawable. Let's not
  3726. + waste more time with X11 calls and just use theirs instead. */
  3727. + free_d3dadapter_drawable(d3d);
  3728. + return race;
  3729. + }
  3730. + XSaveContext(gdi_display, (XID)hwnd, d3d_hwnd_context, (char *)d3d);
  3731. + return d3d;
  3732. +}
  3733. +
  3734. +static void release_d3d_drawable(struct d3d_drawable *d3d)
  3735. +{
  3736. + if (!d3d)
  3737. + ERR("Driver internal error: d3d_drawable is NULL\n");
  3738. + LeaveCriticalSection(&context_section);
  3739. +}
  3740. +
  3741. +static ULONG WINAPI DRI3Present_AddRef(struct DRI3Present *This)
  3742. +{
  3743. + ULONG refs = InterlockedIncrement(&This->refs);
  3744. + TRACE("%p increasing refcount to %u.\n", This, refs);
  3745. + return refs;
  3746. +}
  3747. +
  3748. +static ULONG WINAPI DRI3Present_Release(struct DRI3Present *This)
  3749. +{
  3750. + ULONG refs = InterlockedDecrement(&This->refs);
  3751. + TRACE("%p decreasing refcount to %u.\n", This, refs);
  3752. + if (refs == 0)
  3753. + {
  3754. + /* dtor */
  3755. + (void) nine_unregister_window(This->focus_wnd);
  3756. + if (This->d3d)
  3757. + destroy_d3dadapter_drawable(This->gdi_display, This->d3d->wnd);
  3758. + ChangeDisplaySettingsExW(This->devname, &(This->initial_mode), 0, CDS_FULLSCREEN, NULL);
  3759. + PRESENTDestroy(This->gdi_display, This->present_priv);
  3760. +#ifdef D3D9NINE_DRI2
  3761. + if (is_dri2_fallback)
  3762. + DRI2FallbackDestroy(This->dri2_priv);
  3763. +#endif
  3764. + HeapFree(GetProcessHeap(), 0, This);
  3765. + }
  3766. + return refs;
  3767. +}
  3768. +
  3769. +static HRESULT WINAPI DRI3Present_QueryInterface(struct DRI3Present *This,
  3770. + REFIID riid, void **ppvObject)
  3771. +{
  3772. + if (!ppvObject)
  3773. + return E_POINTER;
  3774. +
  3775. + if (IsEqualGUID(&IID_ID3DPresent, riid) ||
  3776. + IsEqualGUID(&IID_IUnknown, riid))
  3777. + {
  3778. + *ppvObject = This;
  3779. + DRI3Present_AddRef(This);
  3780. + return S_OK;
  3781. + }
  3782. +
  3783. + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
  3784. + *ppvObject = NULL;
  3785. +
  3786. + return E_NOINTERFACE;
  3787. +}
  3788. +
  3789. +static HRESULT DRI3Present_ChangePresentParameters(struct DRI3Present *This,
  3790. + D3DPRESENT_PARAMETERS *params);
  3791. +
  3792. +static HRESULT WINAPI DRI3Present_SetPresentParameters(struct DRI3Present *This,
  3793. + D3DPRESENT_PARAMETERS *pPresentationParameters,
  3794. + D3DDISPLAYMODEEX *pFullscreenDisplayMode)
  3795. +{
  3796. + if (pFullscreenDisplayMode)
  3797. + FIXME("Ignoring pFullscreenDisplayMode\n");
  3798. + return DRI3Present_ChangePresentParameters(This, pPresentationParameters);
  3799. +}
  3800. +
  3801. +static HRESULT WINAPI DRI3Present_D3DWindowBufferFromDmaBuf(struct DRI3Present *This,
  3802. + int dmaBufFd, int width, int height, int stride, int depth,
  3803. + int bpp, struct D3DWindowBuffer **out)
  3804. +{
  3805. + Pixmap pixmap;
  3806. +
  3807. +#ifdef D3D9NINE_DRI2
  3808. + if (is_dri2_fallback)
  3809. + {
  3810. + *out = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  3811. + sizeof(struct D3DWindowBuffer));
  3812. + if (!DRI2FallbackPRESENTPixmap(This->present_priv, This->dri2_priv,
  3813. + dmaBufFd, width, height, stride, depth,
  3814. + bpp, &((*out)->present_pixmap_priv)))
  3815. + {
  3816. + ERR("DRI2FallbackPRESENTPixmap failed\n");
  3817. + HeapFree(GetProcessHeap(), 0, *out);
  3818. + return D3DERR_DRIVERINTERNALERROR;
  3819. + }
  3820. + return D3D_OK;
  3821. + }
  3822. +#endif
  3823. + if (!DRI3PixmapFromDmaBuf(This->gdi_display, DefaultScreen(This->gdi_display),
  3824. + dmaBufFd, width, height, stride, depth, bpp, &pixmap))
  3825. + {
  3826. + ERR("DRI3PixmapFromDmaBuf failed\n");
  3827. + return D3DERR_DRIVERINTERNALERROR;
  3828. + }
  3829. +
  3830. + *out = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  3831. + sizeof(struct D3DWindowBuffer));
  3832. + if (!PRESENTPixmapInit(This->present_priv, pixmap, &((*out)->present_pixmap_priv)))
  3833. + {
  3834. + ERR("PRESENTPixmapInit failed\n");
  3835. + HeapFree(GetProcessHeap(), 0, *out);
  3836. + return D3DERR_DRIVERINTERNALERROR;
  3837. + }
  3838. + return D3D_OK;
  3839. +}
  3840. +
  3841. +static HRESULT WINAPI DRI3Present_DestroyD3DWindowBuffer(struct DRI3Present *This,
  3842. + struct D3DWindowBuffer *buffer)
  3843. +{
  3844. + /* the pixmap is managed by the PRESENT backend.
  3845. + * But if it can delete it right away, we may have
  3846. + * better performance */
  3847. + PRESENTTryFreePixmap(This->gdi_display, buffer->present_pixmap_priv);
  3848. + HeapFree(GetProcessHeap(), 0, buffer);
  3849. + return D3D_OK;
  3850. +}
  3851. +
  3852. +static HRESULT WINAPI DRI3Present_WaitBufferReleased(struct DRI3Present *This,
  3853. + struct D3DWindowBuffer *buffer)
  3854. +{
  3855. + if(!PRESENTWaitPixmapReleased(buffer->present_pixmap_priv))
  3856. + {
  3857. + ERR("PRESENTWaitPixmapReleased failed\n");
  3858. + return D3DERR_DRIVERINTERNALERROR;
  3859. + }
  3860. + return D3D_OK;
  3861. +}
  3862. +
  3863. +static HRESULT WINAPI DRI3Present_FrontBufferCopy(struct DRI3Present *This,
  3864. + struct D3DWindowBuffer *buffer)
  3865. +{
  3866. +#ifdef D3D9NINE_DRI2
  3867. + if (is_dri2_fallback)
  3868. + return D3DERR_DRIVERINTERNALERROR;
  3869. +#endif
  3870. + if (PRESENTHelperCopyFront(This->gdi_display, buffer->present_pixmap_priv))
  3871. + return D3D_OK;
  3872. + else
  3873. + return D3DERR_DRIVERINTERNALERROR;
  3874. +}
  3875. +
  3876. +/* Try to detect client side window decorations by walking the X Drawable up.
  3877. + * In case there's an intermediate Drawable, server side window decorations are used.
  3878. + * TODO: Find a X11 function to query for window decorations.
  3879. + */
  3880. +static BOOL DRI3Present_HasClientSideWindowDecorations(struct DRI3Present *This,
  3881. + HWND hwnd)
  3882. +{
  3883. + struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
  3884. + Window Wroot;
  3885. + Window Wparent;
  3886. + Window *Wchildren;
  3887. + unsigned int numchildren;
  3888. + HWND parent;
  3889. + HDC hdc;
  3890. + BOOL ret = TRUE;
  3891. +
  3892. + parent = GetParent(hwnd);
  3893. + if (!parent)
  3894. + parent = GetDesktopWindow();
  3895. + if (!parent)
  3896. + {
  3897. + ERR("Unexpected error getting the parent hwnd (hwnd=%p)\n", hwnd);
  3898. + return FALSE;
  3899. + }
  3900. +
  3901. + hdc = GetDCEx(hwnd, 0, DCX_CACHE | DCX_CLIPSIBLINGS);
  3902. + if (!hdc)
  3903. + return FALSE;
  3904. + if (ExtEscape(hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
  3905. + sizeof(extesc), (LPSTR)&extesc) <= 0)
  3906. + {
  3907. + ERR("Unexpected error in X Drawable lookup (hwnd=%p, hdc=%p)\n", hwnd, hdc);
  3908. + ReleaseDC(hwnd, hdc);
  3909. + return FALSE;
  3910. + }
  3911. + ReleaseDC(hwnd, hdc);
  3912. +
  3913. + if (XQueryTree(This->gdi_display, extesc.drawable, &Wroot, &Wparent, &Wchildren, &numchildren))
  3914. + {
  3915. + hdc = GetDCEx(parent, 0, DCX_CACHE | DCX_CLIPSIBLINGS);
  3916. + if (!hdc)
  3917. + return FALSE;
  3918. +
  3919. + if (ExtEscape(hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
  3920. + sizeof(extesc), (LPSTR)&extesc) <= 0)
  3921. + {
  3922. + ERR("Unexpected error in X Drawable lookup (hwnd=%p, hdc=%p)\n", parent, hdc);
  3923. + ReleaseDC(parent, hdc);
  3924. + return FALSE;
  3925. + }
  3926. + ReleaseDC(parent, hdc);
  3927. +
  3928. + if (Wparent != extesc.drawable)
  3929. + {
  3930. + /* Found at least one intermediate window */
  3931. + ret = FALSE;
  3932. + }
  3933. + if (Wchildren)
  3934. + free(Wchildren);
  3935. + }
  3936. +
  3937. + return ret;
  3938. +}
  3939. +
  3940. +static HRESULT WINAPI DRI3Present_PresentBuffer( struct DRI3Present *This,
  3941. + struct D3DWindowBuffer *buffer, HWND hWndOverride, const RECT *pSourceRect,
  3942. + const RECT *pDestRect, const RGNDATA *pDirtyRegion, DWORD Flags )
  3943. +{
  3944. + struct d3d_drawable *d3d;
  3945. + RECT dest_translate;
  3946. + RECT offset;
  3947. + HWND hwnd;
  3948. +
  3949. + if (hWndOverride)
  3950. + hwnd = hWndOverride;
  3951. + else if (This->params.hDeviceWindow)
  3952. + hwnd = This->params.hDeviceWindow;
  3953. + else
  3954. + hwnd = This->focus_wnd;
  3955. +
  3956. + d3d = get_d3d_drawable(This->gdi_display, hwnd);
  3957. +
  3958. + if (!d3d)
  3959. + return D3DERR_DRIVERINTERNALERROR;
  3960. +
  3961. + /* TODO: should we use a list here instead ? */
  3962. + if (This->d3d && (This->d3d->wnd != d3d->wnd))
  3963. + destroy_d3dadapter_drawable(This->gdi_display, This->d3d->wnd);
  3964. +
  3965. + This->d3d = d3d;
  3966. +
  3967. + /* In case of client side window decorations we need to add an offset within
  3968. + * the X drawable.
  3969. + * FIXME: Call once on window style / size change */
  3970. + if (DRI3Present_HasClientSideWindowDecorations(This, hwnd))
  3971. + {
  3972. + offset = DRI3Present_GetClientRecWindowRelative(hwnd);
  3973. +
  3974. + if ((offset.top != 0) || (offset.left != 0))
  3975. + {
  3976. + if (!pDestRect)
  3977. + pDestRect = (const RECT *) &offset;
  3978. + else
  3979. + {
  3980. + dest_translate.top = pDestRect->top + offset.top;
  3981. + dest_translate.left = pDestRect->left + offset.left;
  3982. + dest_translate.bottom = pDestRect->bottom + offset.bottom;
  3983. + dest_translate.right = pDestRect->right + offset.right;
  3984. + pDestRect = (const RECT *) &dest_translate;
  3985. + }
  3986. + }
  3987. + }
  3988. +
  3989. + if (!PRESENTPixmap(This->gdi_display, d3d->drawable, buffer->present_pixmap_priv,
  3990. + This->present_interval, This->present_async, This->present_swapeffectcopy,
  3991. + pSourceRect, pDestRect, pDirtyRegion))
  3992. + {
  3993. + release_d3d_drawable(d3d);
  3994. + return D3DERR_DRIVERINTERNALERROR;
  3995. + }
  3996. + release_d3d_drawable(d3d);
  3997. +
  3998. + return D3D_OK;
  3999. +}
  4000. +
  4001. +/* Based on wine's wined3d_get_adapter_raster_status. */
  4002. +static HRESULT WINAPI DRI3Present_GetRasterStatus( struct DRI3Present *This,
  4003. + D3DRASTER_STATUS *pRasterStatus )
  4004. +{
  4005. + LONGLONG freq_per_frame, freq_per_line;
  4006. + LARGE_INTEGER counter, freq_per_sec;
  4007. + unsigned refresh_rate, height;
  4008. +
  4009. + TRACE("This=%p, pRasterStatus=%p\n", This, pRasterStatus);
  4010. +
  4011. + if (!QueryPerformanceCounter(&counter) || !QueryPerformanceFrequency(&freq_per_sec))
  4012. + return D3DERR_INVALIDCALL;
  4013. +
  4014. + if (This->params.Windowed)
  4015. + {
  4016. + refresh_rate = This->initial_mode.dmDisplayFrequency;
  4017. + height = This->initial_mode.dmPelsHeight;
  4018. + }
  4019. + else
  4020. + {
  4021. + refresh_rate = This->params.FullScreen_RefreshRateInHz;
  4022. + height = This->params.BackBufferHeight;
  4023. + }
  4024. +
  4025. + if (refresh_rate == 0)
  4026. + refresh_rate = 60;
  4027. +
  4028. + TRACE("refresh_rate=%u, height=%u\n", refresh_rate, height);
  4029. +
  4030. + freq_per_frame = freq_per_sec.QuadPart / refresh_rate;
  4031. + /* Assume 20 scan lines in the vertical blank. */
  4032. + freq_per_line = freq_per_frame / (height + 20);
  4033. + pRasterStatus->ScanLine = (counter.QuadPart % freq_per_frame) / freq_per_line;
  4034. + if (pRasterStatus->ScanLine < height)
  4035. + pRasterStatus->InVBlank = FALSE;
  4036. + else
  4037. + {
  4038. + pRasterStatus->ScanLine = 0;
  4039. + pRasterStatus->InVBlank = TRUE;
  4040. + }
  4041. +
  4042. + TRACE("Returning fake value, InVBlank %u, ScanLine %u.\n",
  4043. + pRasterStatus->InVBlank, pRasterStatus->ScanLine);
  4044. +
  4045. + return D3D_OK;
  4046. +}
  4047. +
  4048. +static HRESULT WINAPI DRI3Present_GetDisplayMode( struct DRI3Present *This,
  4049. + D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation )
  4050. +{
  4051. + DEVMODEW dm;
  4052. +
  4053. + ZeroMemory(&dm, sizeof(dm));
  4054. + dm.dmSize = sizeof(dm);
  4055. +
  4056. + EnumDisplaySettingsExW(This->devname, ENUM_CURRENT_SETTINGS, &dm, 0);
  4057. + pMode->Width = dm.dmPelsWidth;
  4058. + pMode->Height = dm.dmPelsHeight;
  4059. + pMode->RefreshRate = dm.dmDisplayFrequency;
  4060. + pMode->ScanLineOrdering = (dm.dmDisplayFlags & DM_INTERLACED) ?
  4061. + D3DSCANLINEORDERING_INTERLACED : D3DSCANLINEORDERING_PROGRESSIVE;
  4062. +
  4063. + /* XXX This is called "guessing" */
  4064. + switch (dm.dmBitsPerPel)
  4065. + {
  4066. + case 32: pMode->Format = D3DFMT_X8R8G8B8; break;
  4067. + case 24: pMode->Format = D3DFMT_R8G8B8; break;
  4068. + case 16: pMode->Format = D3DFMT_R5G6B5; break;
  4069. + default:
  4070. + WARN("Unknown display format with %u bpp.\n", dm.dmBitsPerPel);
  4071. + pMode->Format = D3DFMT_UNKNOWN;
  4072. + }
  4073. +
  4074. + switch (dm.dmDisplayOrientation)
  4075. + {
  4076. + case DMDO_DEFAULT: *pRotation = D3DDISPLAYROTATION_IDENTITY; break;
  4077. + case DMDO_90: *pRotation = D3DDISPLAYROTATION_90; break;
  4078. + case DMDO_180: *pRotation = D3DDISPLAYROTATION_180; break;
  4079. + case DMDO_270: *pRotation = D3DDISPLAYROTATION_270; break;
  4080. + default:
  4081. + WARN("Unknown display rotation %u.\n", dm.dmDisplayOrientation);
  4082. + *pRotation = D3DDISPLAYROTATION_IDENTITY;
  4083. + }
  4084. +
  4085. + return D3D_OK;
  4086. +}
  4087. +
  4088. +static HRESULT WINAPI DRI3Present_GetPresentStats( struct DRI3Present *This, D3DPRESENTSTATS *pStats )
  4089. +{
  4090. + FIXME("(%p, %p), stub!\n", This, pStats);
  4091. + return D3DERR_INVALIDCALL;
  4092. +}
  4093. +
  4094. +static HRESULT WINAPI DRI3Present_GetCursorPos( struct DRI3Present *This, POINT *pPoint )
  4095. +{
  4096. + BOOL ok;
  4097. + HWND draw_window;
  4098. +
  4099. + if (!pPoint)
  4100. + return D3DERR_INVALIDCALL;
  4101. +
  4102. + draw_window = This->params.hDeviceWindow ?
  4103. + This->params.hDeviceWindow : This->focus_wnd;
  4104. +
  4105. + ok = GetCursorPos(pPoint);
  4106. + ok = ok && ScreenToClient(draw_window, pPoint);
  4107. + return ok ? S_OK : D3DERR_DRIVERINTERNALERROR;
  4108. +}
  4109. +
  4110. +static HRESULT WINAPI DRI3Present_SetCursorPos( struct DRI3Present *This, POINT *pPoint )
  4111. +{
  4112. + BOOL ok;
  4113. + POINT real_pos;
  4114. +
  4115. + if (!pPoint)
  4116. + return D3DERR_INVALIDCALL;
  4117. +
  4118. + ok = SetCursorPos(pPoint->x, pPoint->y);
  4119. + if (!ok)
  4120. + goto error;
  4121. +
  4122. + ok = GetCursorPos(&real_pos);
  4123. + if (!ok || real_pos.x != pPoint->x || real_pos.y != pPoint->y)
  4124. + goto error;
  4125. +
  4126. + return D3D_OK;
  4127. +
  4128. +error:
  4129. + SetCursor(NULL); /* Hide cursor rather than put wrong pos */
  4130. + return D3DERR_DRIVERINTERNALERROR;
  4131. +}
  4132. +
  4133. +/* Note: assuming 32x32 cursor */
  4134. +static HRESULT WINAPI DRI3Present_SetCursor( struct DRI3Present *This, void *pBitmap,
  4135. + POINT *pHotspot, BOOL bShow )
  4136. +{
  4137. + if (pBitmap)
  4138. + {
  4139. + ICONINFO info;
  4140. + HCURSOR cursor;
  4141. +
  4142. + DWORD mask[32];
  4143. + memset(mask, ~0, sizeof(mask));
  4144. +
  4145. + if (!pHotspot)
  4146. + return D3DERR_INVALIDCALL;
  4147. + info.fIcon = FALSE;
  4148. + info.xHotspot = pHotspot->x;
  4149. + info.yHotspot = pHotspot->y;
  4150. + info.hbmMask = CreateBitmap(32, 32, 1, 1, mask);
  4151. + info.hbmColor = CreateBitmap(32, 32, 1, 32, pBitmap);
  4152. +
  4153. + cursor = CreateIconIndirect(&info);
  4154. + if (info.hbmMask) DeleteObject(info.hbmMask);
  4155. + if (info.hbmColor) DeleteObject(info.hbmColor);
  4156. + if (cursor)
  4157. + DestroyCursor(This->hCursor);
  4158. + This->hCursor = cursor;
  4159. + }
  4160. + SetCursor(bShow ? This->hCursor : NULL);
  4161. +
  4162. + return D3D_OK;
  4163. +}
  4164. +
  4165. +static HRESULT WINAPI DRI3Present_SetGammaRamp( struct DRI3Present *This,
  4166. + const D3DGAMMARAMP *pRamp, HWND hWndOverride )
  4167. +{
  4168. + HWND hWnd = hWndOverride ? hWndOverride : This->focus_wnd;
  4169. + HDC hdc;
  4170. + BOOL ok;
  4171. + if (!pRamp)
  4172. + return D3DERR_INVALIDCALL;
  4173. +
  4174. + hdc = GetDC(hWnd);
  4175. + ok = SetDeviceGammaRamp(hdc, (void *)pRamp);
  4176. + ReleaseDC(hWnd, hdc);
  4177. + return ok ? D3D_OK : D3DERR_DRIVERINTERNALERROR;
  4178. +}
  4179. +
  4180. +static HRESULT WINAPI DRI3Present_GetWindowInfo( struct DRI3Present *This,
  4181. + HWND hWnd, int *width, int *height, int *depth )
  4182. +{
  4183. + HRESULT hr;
  4184. + RECT pRect;
  4185. +
  4186. + if (!hWnd)
  4187. + hWnd = This->focus_wnd;
  4188. + hr = GetClientRect(hWnd, &pRect);
  4189. + if (!hr)
  4190. + return D3DERR_INVALIDCALL;
  4191. + *width = pRect.right - pRect.left;
  4192. + *height = pRect.bottom - pRect.top;
  4193. + *depth = 24; //TODO
  4194. + return D3D_OK;
  4195. +}
  4196. +
  4197. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 1
  4198. +static BOOL WINAPI DRI3Present_GetWindowOccluded(struct DRI3Present *This)
  4199. +{
  4200. + return This->occluded;
  4201. +}
  4202. +#endif
  4203. +
  4204. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 2
  4205. +static BOOL WINAPI DRI3Present_ResolutionMismatch(struct DRI3Present *This)
  4206. +{
  4207. + /* The resolution might change due to a third party app.
  4208. + * Poll this function to get the device's resolution match.
  4209. + * A device reset is required to restore the requested resolution.
  4210. + */
  4211. + return This->resolution_mismatch;
  4212. +}
  4213. +
  4214. +static HANDLE WINAPI DRI3Present_CreateThread( struct DRI3Present *This,
  4215. + void *pThreadfunc, void *pParam )
  4216. +{
  4217. + LPTHREAD_START_ROUTINE lpStartAddress =
  4218. + (LPTHREAD_START_ROUTINE) pThreadfunc;
  4219. +
  4220. + return CreateThread(NULL, 0, lpStartAddress, pParam, 0, NULL);
  4221. +}
  4222. +
  4223. +static BOOL WINAPI DRI3Present_WaitForThread( struct DRI3Present *This, HANDLE thread )
  4224. +{
  4225. + DWORD ExitCode = 0;
  4226. + while (GetExitCodeThread(thread, &ExitCode) && ExitCode == STILL_ACTIVE)
  4227. + Sleep(10);
  4228. +
  4229. + return TRUE;
  4230. +}
  4231. +#endif
  4232. +
  4233. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 3
  4234. +static HRESULT WINAPI DRI3Present_SetPresentParameters2( struct DRI3Present *This, D3DPRESENT_PARAMETERS2 *pParams )
  4235. +{
  4236. + This->allow_discard_delayed_release = pParams->AllowDISCARDDelayedRelease;
  4237. + This->tear_free_discard = pParams->AllowDISCARDDelayedRelease && pParams->TearFreeDISCARD;
  4238. + return D3D_OK;
  4239. +}
  4240. +
  4241. +static BOOL WINAPI DRI3Present_IsBufferReleased( struct DRI3Present *This, struct D3DWindowBuffer *buffer )
  4242. +{
  4243. + return PRESENTIsPixmapReleased(buffer->present_pixmap_priv);
  4244. +}
  4245. +
  4246. +static HRESULT WINAPI DRI3Present_WaitBufferReleaseEvent( struct DRI3Present *This )
  4247. +{
  4248. + PRESENTWaitReleaseEvent(This->present_priv);
  4249. + return D3D_OK;
  4250. +}
  4251. +#endif
  4252. +
  4253. +/*----------*/
  4254. +
  4255. +static ID3DPresentVtbl DRI3Present_vtable = {
  4256. + (void *)DRI3Present_QueryInterface,
  4257. + (void *)DRI3Present_AddRef,
  4258. + (void *)DRI3Present_Release,
  4259. + (void *)DRI3Present_SetPresentParameters,
  4260. + (void *)DRI3Present_D3DWindowBufferFromDmaBuf,
  4261. + (void *)DRI3Present_DestroyD3DWindowBuffer,
  4262. + (void *)DRI3Present_WaitBufferReleased,
  4263. + (void *)DRI3Present_FrontBufferCopy,
  4264. + (void *)DRI3Present_PresentBuffer,
  4265. + (void *)DRI3Present_GetRasterStatus,
  4266. + (void *)DRI3Present_GetDisplayMode,
  4267. + (void *)DRI3Present_GetPresentStats,
  4268. + (void *)DRI3Present_GetCursorPos,
  4269. + (void *)DRI3Present_SetCursorPos,
  4270. + (void *)DRI3Present_SetCursor,
  4271. + (void *)DRI3Present_SetGammaRamp,
  4272. + (void *)DRI3Present_GetWindowInfo,
  4273. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 1
  4274. + (void *)DRI3Present_GetWindowOccluded,
  4275. +#endif
  4276. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 2
  4277. + (void *)DRI3Present_ResolutionMismatch,
  4278. + (void *)DRI3Present_CreateThread,
  4279. + (void *)DRI3Present_WaitForThread,
  4280. +#endif
  4281. +#if WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR >= 3
  4282. + (void *)DRI3Present_SetPresentParameters2,
  4283. + (void *)DRI3Present_IsBufferReleased,
  4284. + (void *)DRI3Present_WaitBufferReleaseEvent,
  4285. +#endif
  4286. +};
  4287. +
  4288. +/* The following code is based on WINE's wined3d/device.c and
  4289. + * wined3d/swapchain.c and WINE's d3d9 files. */
  4290. +
  4291. +static LONG fullscreen_style(LONG style)
  4292. +{
  4293. + /* Make sure the window is managed, otherwise we won't get keyboard input. */
  4294. + style |= WS_POPUP | WS_SYSMENU;
  4295. + style &= ~(WS_CAPTION | WS_THICKFRAME);
  4296. +
  4297. + return style;
  4298. +}
  4299. +
  4300. +static LONG fullscreen_exstyle(LONG exstyle)
  4301. +{
  4302. + /* Filter out window decorations. */
  4303. + exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
  4304. +
  4305. + return exstyle;
  4306. +}
  4307. +
  4308. +static HRESULT DRI3Present_ChangeDisplaySettingsIfNeccessary(struct DRI3Present *This, DEVMODEW *new_mode)
  4309. +{
  4310. + DEVMODEW current_mode;
  4311. + LONG hr;
  4312. +
  4313. + /* Filter invalid resolution */
  4314. + if (!new_mode->dmPelsWidth || !new_mode->dmPelsHeight)
  4315. + return D3DERR_INVALIDCALL;
  4316. +
  4317. + /* Ignore invalid frequency requested */
  4318. + if (new_mode->dmDisplayFrequency > 1000)
  4319. + new_mode->dmDisplayFrequency = 0;
  4320. +
  4321. + ZeroMemory(&current_mode, sizeof(DEVMODEW));
  4322. + current_mode.dmSize = sizeof(DEVMODEW);
  4323. + /* Only change the mode if necessary. */
  4324. + if (!EnumDisplaySettingsW(This->devname, ENUM_CURRENT_SETTINGS, &current_mode))
  4325. + ERR("Failed to get current display mode.\n");
  4326. + else if (current_mode.dmPelsWidth != new_mode->dmPelsWidth
  4327. + || current_mode.dmPelsHeight != new_mode->dmPelsHeight
  4328. + || (current_mode.dmDisplayFrequency != new_mode->dmDisplayFrequency
  4329. + && (new_mode->dmFields & DM_DISPLAYFREQUENCY)))
  4330. + {
  4331. + hr = ChangeDisplaySettingsExW(This->devname, new_mode, 0, CDS_FULLSCREEN, NULL);
  4332. + if (hr != DISP_CHANGE_SUCCESSFUL)
  4333. + {
  4334. + /* try again without display RefreshRate */
  4335. + if (new_mode->dmFields & DM_DISPLAYFREQUENCY)
  4336. + {
  4337. + new_mode->dmFields &= ~DM_DISPLAYFREQUENCY;
  4338. + new_mode->dmDisplayFrequency = 0;
  4339. + hr = ChangeDisplaySettingsExW(This->devname, new_mode, 0, CDS_FULLSCREEN, NULL);
  4340. + if (hr != DISP_CHANGE_SUCCESSFUL)
  4341. + {
  4342. + ERR("ChangeDisplaySettingsExW failed with 0x%08X\n", hr);
  4343. + return D3DERR_INVALIDCALL;
  4344. + }
  4345. + }
  4346. + else
  4347. + {
  4348. + ERR("ChangeDisplaySettingsExW failed with 0x%08X\n", hr);
  4349. + return D3DERR_INVALIDCALL;
  4350. + }
  4351. + }
  4352. + }
  4353. + return D3D_OK;
  4354. +}
  4355. +
  4356. +LRESULT device_process_message(struct DRI3Present *present, HWND window, BOOL unicode,
  4357. + UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
  4358. +{
  4359. + boolean drop_wnd_messages;
  4360. + DEVMODEW current_mode;
  4361. + DEVMODEW new_mode;
  4362. +
  4363. + TRACE("Got message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
  4364. + window, message, wparam, lparam);
  4365. +
  4366. + if (present->drop_wnd_messages && message != WM_DISPLAYCHANGE)
  4367. + {
  4368. + TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
  4369. + window, message, wparam, lparam);
  4370. + if (unicode)
  4371. + return DefWindowProcW(window, message, wparam, lparam);
  4372. + else
  4373. + return DefWindowProcA(window, message, wparam, lparam);
  4374. + }
  4375. +
  4376. + if (message == WM_DESTROY)
  4377. + {
  4378. + TRACE("unregister window %p.\n", window);
  4379. + (void) nine_unregister_window(window);
  4380. + }
  4381. + else if (message == WM_DISPLAYCHANGE)
  4382. + {
  4383. + /* Ex restores display mode, while non Ex requires the
  4384. + * user to call Device::Reset() */
  4385. + ZeroMemory(&current_mode, sizeof(DEVMODEW));
  4386. + current_mode.dmSize = sizeof(current_mode);
  4387. + if (!present->ex &&
  4388. + !present->params.Windowed &&
  4389. + present->params.hDeviceWindow &&
  4390. + EnumDisplaySettingsW(present->devname, ENUM_CURRENT_SETTINGS, &current_mode) &&
  4391. + (current_mode.dmPelsWidth != present->params.BackBufferWidth ||
  4392. + current_mode.dmPelsHeight != present->params.BackBufferHeight))
  4393. + {
  4394. + present->resolution_mismatch = TRUE;
  4395. + }
  4396. + else
  4397. + {
  4398. + present->resolution_mismatch = FALSE;
  4399. + }
  4400. + }
  4401. + else if (message == WM_ACTIVATEAPP)
  4402. + {
  4403. + drop_wnd_messages = present->drop_wnd_messages;
  4404. + present->drop_wnd_messages = TRUE;
  4405. +
  4406. + if (wparam == WA_INACTIVE)
  4407. + {
  4408. + present->occluded = TRUE;
  4409. + present->reapply_mode = TRUE;
  4410. +
  4411. + ZeroMemory(&new_mode, sizeof(DEVMODEW));
  4412. + new_mode.dmSize = sizeof(new_mode);
  4413. + if (EnumDisplaySettingsW(present->devname, ENUM_REGISTRY_SETTINGS, &new_mode))
  4414. + DRI3Present_ChangeDisplaySettingsIfNeccessary(present, &new_mode);
  4415. +
  4416. + if (!present->no_window_changes &&
  4417. + IsWindowVisible(present->params.hDeviceWindow))
  4418. + ShowWindow(present->params.hDeviceWindow, SW_MINIMIZE);
  4419. + }
  4420. + else
  4421. + {
  4422. + present->occluded = FALSE;
  4423. +
  4424. + if (!present->no_window_changes)
  4425. + {
  4426. + /* restore window */
  4427. + SetWindowPos(present->params.hDeviceWindow, NULL, 0, 0,
  4428. + present->params.BackBufferWidth, present->params.BackBufferHeight,
  4429. + SWP_NOACTIVATE | SWP_NOZORDER);
  4430. + }
  4431. +
  4432. + if (present->ex)
  4433. + {
  4434. + ZeroMemory(&new_mode, sizeof(DEVMODEW));
  4435. + new_mode.dmSize = sizeof(new_mode);
  4436. + new_mode.dmPelsWidth = present->params.BackBufferWidth;
  4437. + new_mode.dmPelsHeight = present->params.BackBufferHeight;
  4438. + new_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
  4439. + if (present->params.FullScreen_RefreshRateInHz)
  4440. + {
  4441. + new_mode.dmFields |= DM_DISPLAYFREQUENCY;
  4442. + new_mode.dmDisplayFrequency = present->params.FullScreen_RefreshRateInHz;
  4443. + }
  4444. + DRI3Present_ChangeDisplaySettingsIfNeccessary(present, &new_mode);
  4445. + }
  4446. + }
  4447. + present->drop_wnd_messages = drop_wnd_messages;
  4448. + }
  4449. + else if (message == WM_SYSCOMMAND)
  4450. + {
  4451. + if (wparam == SC_RESTORE)
  4452. + {
  4453. + if (unicode)
  4454. + DefWindowProcW(window, message, wparam, lparam);
  4455. + else
  4456. + DefWindowProcA(window, message, wparam, lparam);
  4457. + }
  4458. + }
  4459. +
  4460. + if (unicode)
  4461. + return CallWindowProcW(proc, window, message, wparam, lparam);
  4462. + else
  4463. + return CallWindowProcA(proc, window, message, wparam, lparam);
  4464. +}
  4465. +
  4466. +static void setup_fullscreen_window(struct DRI3Present *This,
  4467. + HWND hwnd, int w, int h)
  4468. +{
  4469. + boolean drop_wnd_messages;
  4470. + LONG style, style_ex;
  4471. +
  4472. + This->style = GetWindowLongW(hwnd, GWL_STYLE);
  4473. + This->style_ex = GetWindowLongW(hwnd, GWL_EXSTYLE);
  4474. +
  4475. + style = fullscreen_style(This->style);
  4476. + style_ex = fullscreen_exstyle(This->style_ex);
  4477. +
  4478. + drop_wnd_messages = This->drop_wnd_messages;
  4479. + This->drop_wnd_messages = TRUE;
  4480. +
  4481. + SetWindowLongW(hwnd, GWL_STYLE, style);
  4482. + SetWindowLongW(hwnd, GWL_EXSTYLE, style_ex);
  4483. +
  4484. + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, w, h,
  4485. + SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
  4486. +
  4487. + This->drop_wnd_messages = drop_wnd_messages;
  4488. +}
  4489. +
  4490. +static void move_fullscreen_window(struct DRI3Present *This,
  4491. + HWND hwnd, int w, int h)
  4492. +{
  4493. + boolean drop_wnd_messages;
  4494. + LONG style, style_ex;
  4495. +
  4496. + /* move draw window back to place */
  4497. +
  4498. + style = GetWindowLongW(hwnd, GWL_STYLE);
  4499. + style_ex = GetWindowLongW(hwnd, GWL_EXSTYLE);
  4500. +
  4501. + style = fullscreen_style(style);
  4502. + style_ex = fullscreen_exstyle(style_ex);
  4503. +
  4504. + drop_wnd_messages = This->drop_wnd_messages;
  4505. + This->drop_wnd_messages = TRUE;
  4506. + SetWindowLongW(hwnd, GWL_STYLE, style);
  4507. + SetWindowLongW(hwnd, GWL_EXSTYLE, style_ex);
  4508. + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, w, h,
  4509. + SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
  4510. + This->drop_wnd_messages = drop_wnd_messages;
  4511. +}
  4512. +
  4513. +static void restore_fullscreen_window(struct DRI3Present *This,
  4514. + HWND hwnd)
  4515. +{
  4516. + boolean drop_wnd_messages;
  4517. + LONG style, style_ex;
  4518. +
  4519. + /* switch from fullscreen to window */
  4520. + style = GetWindowLongW(hwnd, GWL_STYLE);
  4521. + style_ex = GetWindowLongW(hwnd, GWL_EXSTYLE);
  4522. + /* These flags are set by us, not the
  4523. + * application, and we want to ignore them in the test below, since it's
  4524. + * not the application's fault that they changed. Additionally, we want to
  4525. + * preserve the current status of these flags (i.e. don't restore them) to
  4526. + * more closely emulate the behavior of Direct3D, which leaves these flags
  4527. + * alone when returning to windowed mode. */
  4528. + This->style ^= (This->style ^ style) & WS_VISIBLE;
  4529. + This->style_ex ^= (This->style_ex ^ style_ex) & WS_EX_TOPMOST;
  4530. +
  4531. + /* Only restore the style if the application didn't modify it during the
  4532. + * fullscreen phase. Some applications change it before calling Reset()
  4533. + * when switching between windowed and fullscreen modes (HL2), some
  4534. + * depend on the original style (Eve Online). */
  4535. + drop_wnd_messages = This->drop_wnd_messages;
  4536. + This->drop_wnd_messages = TRUE;
  4537. + if (style == fullscreen_style(This->style) &&
  4538. + style_ex == fullscreen_exstyle(This->style_ex))
  4539. + {
  4540. + SetWindowLongW(hwnd, GWL_STYLE, This->style);
  4541. + SetWindowLongW(hwnd, GWL_EXSTYLE, This->style_ex);
  4542. + }
  4543. + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED |
  4544. + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
  4545. + SWP_NOACTIVATE);
  4546. + This->drop_wnd_messages = drop_wnd_messages;
  4547. +
  4548. + This->style = 0;
  4549. + This->style_ex = 0;
  4550. +}
  4551. +
  4552. +static void DRI3Present_UpdatePresentationInterval(struct DRI3Present *This)
  4553. +{
  4554. + switch(This->params.PresentationInterval)
  4555. + {
  4556. + case D3DPRESENT_INTERVAL_DEFAULT:
  4557. + case D3DPRESENT_INTERVAL_ONE:
  4558. + This->present_interval = 1;
  4559. + This->present_async = FALSE;
  4560. + break;
  4561. + case D3DPRESENT_INTERVAL_TWO:
  4562. + This->present_interval = 2;
  4563. + This->present_async = FALSE;
  4564. + break;
  4565. + case D3DPRESENT_INTERVAL_THREE:
  4566. + This->present_interval = 3;
  4567. + This->present_async = FALSE;
  4568. + break;
  4569. + case D3DPRESENT_INTERVAL_FOUR:
  4570. + This->present_interval = 4;
  4571. + This->present_async = FALSE;
  4572. + break;
  4573. + case D3DPRESENT_INTERVAL_IMMEDIATE:
  4574. + default:
  4575. + This->present_interval = 0;
  4576. + This->present_async =
  4577. + !(This->params.SwapEffect == D3DSWAPEFFECT_DISCARD &&
  4578. + This->tear_free_discard);
  4579. + break;
  4580. + }
  4581. +
  4582. + /* D3DSWAPEFFECT_COPY: Force Copy.
  4583. + * This->present_interval == 0: Force Copy to have buffers
  4584. + * release as soon as possible (the display server/compositor
  4585. + * won't hold any buffer), unless DISCARD and
  4586. + * allow_discard_delayed_release */
  4587. + This->present_swapeffectcopy =
  4588. + This->params.SwapEffect == D3DSWAPEFFECT_COPY ||
  4589. + (This->present_interval == 0 &&
  4590. + !(This->params.SwapEffect == D3DSWAPEFFECT_DISCARD &&
  4591. + This->allow_discard_delayed_release));
  4592. +}
  4593. +
  4594. +static HRESULT DRI3Present_ChangePresentParameters(struct DRI3Present *This,
  4595. + D3DPRESENT_PARAMETERS *params)
  4596. +{
  4597. + HWND focus_window = This->focus_wnd ? This->focus_wnd : params->hDeviceWindow;
  4598. + RECT rect;
  4599. + DEVMODEW new_mode;
  4600. + HRESULT hr;
  4601. + boolean drop_wnd_messages;
  4602. +
  4603. + TRACE("This=%p, params=%p, focus_window=%p, params->hDeviceWindow=%p\n",
  4604. + This, params, focus_window, params->hDeviceWindow);
  4605. +
  4606. + This->params.SwapEffect = params->SwapEffect;
  4607. + This->params.AutoDepthStencilFormat = params->AutoDepthStencilFormat;
  4608. + This->params.Flags = params->Flags;
  4609. + This->params.FullScreen_RefreshRateInHz = params->FullScreen_RefreshRateInHz;
  4610. + This->params.PresentationInterval = params->PresentationInterval;
  4611. + This->params.EnableAutoDepthStencil = params->EnableAutoDepthStencil;
  4612. + if (!params->hDeviceWindow)
  4613. + params->hDeviceWindow = This->params.hDeviceWindow;
  4614. + else
  4615. + This->params.hDeviceWindow = params->hDeviceWindow;
  4616. +
  4617. + if ((This->params.BackBufferWidth != params->BackBufferWidth) ||
  4618. + (This->params.BackBufferHeight != params->BackBufferHeight) ||
  4619. + (This->params.Windowed != params->Windowed) ||
  4620. + This->reapply_mode)
  4621. + {
  4622. + This->reapply_mode = FALSE;
  4623. +
  4624. + if (!params->Windowed)
  4625. + {
  4626. + TRACE("Setting fullscreen mode: %dx%d@%d\n", params->BackBufferWidth,
  4627. + params->BackBufferHeight, params->FullScreen_RefreshRateInHz);
  4628. +
  4629. + /* switch display mode */
  4630. + ZeroMemory(&new_mode, sizeof(DEVMODEW));
  4631. + new_mode.dmPelsWidth = params->BackBufferWidth;
  4632. + new_mode.dmPelsHeight = params->BackBufferHeight;
  4633. + new_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
  4634. + if (params->FullScreen_RefreshRateInHz)
  4635. + {
  4636. + new_mode.dmFields |= DM_DISPLAYFREQUENCY;
  4637. + new_mode.dmDisplayFrequency = params->FullScreen_RefreshRateInHz;
  4638. + }
  4639. + new_mode.dmSize = sizeof(DEVMODEW);
  4640. + hr = DRI3Present_ChangeDisplaySettingsIfNeccessary(This, &new_mode);
  4641. + if (FAILED(hr))
  4642. + return hr;
  4643. +
  4644. + /* Dirty as BackBufferWidth and BackBufferHeight hasn't been set yet */
  4645. + This->resolution_mismatch = FALSE;
  4646. + }
  4647. + else if(!This->params.Windowed && params->Windowed)
  4648. + {
  4649. + TRACE("Setting fullscreen mode: %dx%d@%d\n", This->initial_mode.dmPelsWidth,
  4650. + This->initial_mode.dmPelsHeight, This->initial_mode.dmDisplayFrequency);
  4651. +
  4652. + hr = DRI3Present_ChangeDisplaySettingsIfNeccessary(This, &This->initial_mode);
  4653. + if (FAILED(hr))
  4654. + return hr;
  4655. +
  4656. + /* Dirty as BackBufferWidth and BackBufferHeight hasn't been set yet */
  4657. + This->resolution_mismatch = FALSE;
  4658. + }
  4659. +
  4660. + if (This->params.Windowed)
  4661. + {
  4662. + if (!params->Windowed)
  4663. + {
  4664. + /* switch from window to fullscreen */
  4665. + if (!nine_register_window(focus_window, This))
  4666. + return D3DERR_INVALIDCALL;
  4667. +
  4668. + SetWindowPos(focus_window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  4669. +
  4670. + setup_fullscreen_window(This, params->hDeviceWindow,
  4671. + params->BackBufferWidth, params->BackBufferHeight);
  4672. + }
  4673. + }
  4674. + else
  4675. + {
  4676. + if (!params->Windowed)
  4677. + {
  4678. + /* switch from fullscreen to fullscreen */
  4679. + drop_wnd_messages = This->drop_wnd_messages;
  4680. + This->drop_wnd_messages = TRUE;
  4681. + MoveWindow(params->hDeviceWindow, 0, 0,
  4682. + params->BackBufferWidth,
  4683. + params->BackBufferHeight,
  4684. + TRUE);
  4685. + This->drop_wnd_messages = drop_wnd_messages;
  4686. + }
  4687. + else if (This->style || This->style_ex)
  4688. + {
  4689. + restore_fullscreen_window(This, params->hDeviceWindow);
  4690. + }
  4691. +
  4692. + if (params->Windowed && !nine_unregister_window(focus_window))
  4693. + ERR("Window %p is not registered with nine.\n", focus_window);
  4694. + }
  4695. + This->params.Windowed = params->Windowed;
  4696. + }
  4697. + else if (!params->Windowed)
  4698. + {
  4699. + move_fullscreen_window(This, params->hDeviceWindow, params->BackBufferWidth, params->BackBufferHeight);
  4700. + }
  4701. + else
  4702. + {
  4703. + TRACE("Nothing changed.\n");
  4704. + }
  4705. + if (!params->BackBufferWidth || !params->BackBufferHeight) {
  4706. + if (!params->Windowed)
  4707. + return D3DERR_INVALIDCALL;
  4708. +
  4709. + if (!GetClientRect(params->hDeviceWindow, &rect))
  4710. + return D3DERR_INVALIDCALL;
  4711. +
  4712. + if (params->BackBufferWidth == 0)
  4713. + params->BackBufferWidth = rect.right - rect.left;
  4714. +
  4715. + if (params->BackBufferHeight == 0)
  4716. + params->BackBufferHeight = rect.bottom - rect.top;
  4717. + }
  4718. +
  4719. + /* Set as last in case of failed reset those aren't updated */
  4720. + This->params.BackBufferWidth = params->BackBufferWidth;
  4721. + This->params.BackBufferHeight = params->BackBufferHeight;
  4722. + This->params.BackBufferFormat = params->BackBufferFormat;
  4723. + This->params.BackBufferCount = params->BackBufferCount;
  4724. + This->params.MultiSampleType = params->MultiSampleType;
  4725. + This->params.MultiSampleQuality = params->MultiSampleQuality;
  4726. +
  4727. + DRI3Present_UpdatePresentationInterval(This);
  4728. +
  4729. + return D3D_OK;
  4730. +}
  4731. +
  4732. +/* The following code isn't based on WINE's wined3d or d3d9. */
  4733. +
  4734. +static HRESULT DRI3Present_new(Display *gdi_display, const WCHAR *devname,
  4735. + D3DPRESENT_PARAMETERS *params, HWND focus_wnd, struct DRI3Present **out,
  4736. + boolean ex, boolean no_window_changes)
  4737. +{
  4738. + struct DRI3Present *This;
  4739. + HWND focus_window;
  4740. + DEVMODEW new_mode;
  4741. + HRESULT hr;
  4742. + RECT rect;
  4743. +
  4744. + if (!focus_wnd && !params->hDeviceWindow)
  4745. + {
  4746. + ERR("No focus HWND specified for presentation backend.\n");
  4747. + return D3DERR_INVALIDCALL;
  4748. + }
  4749. +
  4750. + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  4751. + sizeof(struct DRI3Present));
  4752. + if (!This)
  4753. + {
  4754. + ERR("Out of memory.\n");
  4755. + return E_OUTOFMEMORY;
  4756. + }
  4757. +
  4758. + This->gdi_display = gdi_display;
  4759. + This->vtable = &DRI3Present_vtable;
  4760. + This->refs = 1;
  4761. + This->focus_wnd = focus_wnd;
  4762. + This->ex = ex;
  4763. + This->no_window_changes = no_window_changes;
  4764. +
  4765. + /* store current resolution */
  4766. + ZeroMemory(&(This->initial_mode), sizeof(This->initial_mode));
  4767. + This->initial_mode.dmSize = sizeof(This->initial_mode);
  4768. + EnumDisplaySettingsExW(This->devname, ENUM_CURRENT_SETTINGS, &(This->initial_mode), 0);
  4769. +
  4770. + if (!params->hDeviceWindow)
  4771. + params->hDeviceWindow = This->focus_wnd;
  4772. +
  4773. + if (!params->Windowed) {
  4774. + focus_window = This->focus_wnd ? This->focus_wnd : params->hDeviceWindow;
  4775. +
  4776. + if (!nine_register_window(focus_window, This))
  4777. + return D3DERR_INVALIDCALL;
  4778. +
  4779. + SetWindowPos(focus_window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  4780. +
  4781. + /* switch display mode */
  4782. + ZeroMemory(&new_mode, sizeof(DEVMODEW));
  4783. + new_mode.dmSize = sizeof(DEVMODEW);
  4784. + new_mode.dmPelsWidth = params->BackBufferWidth;
  4785. + new_mode.dmPelsHeight = params->BackBufferHeight;
  4786. + new_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
  4787. +
  4788. + if (params->FullScreen_RefreshRateInHz)
  4789. + {
  4790. + new_mode.dmFields |= DM_DISPLAYFREQUENCY;
  4791. + new_mode.dmDisplayFrequency = params->FullScreen_RefreshRateInHz;
  4792. + }
  4793. +
  4794. + hr = DRI3Present_ChangeDisplaySettingsIfNeccessary(This, &new_mode);
  4795. + if (FAILED(hr))
  4796. + {
  4797. + nine_unregister_window(focus_window);
  4798. + HeapFree(GetProcessHeap(), 0, This);
  4799. + return hr;
  4800. + }
  4801. +
  4802. + /* Dirty as BackBufferWidth and BackBufferHeight hasn't been set yet */
  4803. + This->resolution_mismatch = FALSE;
  4804. +
  4805. + setup_fullscreen_window(This, params->hDeviceWindow,
  4806. + params->BackBufferWidth, params->BackBufferHeight);
  4807. + } else {
  4808. + GetClientRect(params->hDeviceWindow, &rect);
  4809. + if (!params->BackBufferWidth || !params->BackBufferHeight) {
  4810. +
  4811. + if (params->BackBufferWidth == 0)
  4812. + params->BackBufferWidth = rect.right - rect.left;
  4813. +
  4814. + if (params->BackBufferHeight == 0)
  4815. + params->BackBufferHeight = rect.bottom - rect.top;
  4816. + }
  4817. + }
  4818. +
  4819. + This->params = *params;
  4820. +
  4821. + DRI3Present_UpdatePresentationInterval(This);
  4822. +
  4823. + strcpyW(This->devname, devname);
  4824. +
  4825. + PRESENTInit(gdi_display, &(This->present_priv));
  4826. +#ifdef D3D9NINE_DRI2
  4827. + if (is_dri2_fallback && !DRI2FallbackInit(gdi_display, &(This->dri2_priv)))
  4828. + return D3DERR_INVALIDCALL;
  4829. +#endif
  4830. + *out = This;
  4831. +
  4832. + return D3D_OK;
  4833. +}
  4834. +
  4835. +struct DRI3PresentGroup
  4836. +{
  4837. + /* COM vtable */
  4838. + void *vtable;
  4839. + /* IUnknown reference count */
  4840. + LONG refs;
  4841. +
  4842. + boolean ex;
  4843. + struct DRI3Present **present_backends;
  4844. + unsigned npresent_backends;
  4845. + Display *gdi_display;
  4846. + boolean no_window_changes;
  4847. +};
  4848. +
  4849. +static ULONG WINAPI DRI3PresentGroup_AddRef(struct DRI3PresentGroup *This)
  4850. +{
  4851. + ULONG refs = InterlockedIncrement(&This->refs);
  4852. + TRACE("%p increasing refcount to %u.\n", This, refs);
  4853. + return refs;
  4854. +}
  4855. +
  4856. +static ULONG WINAPI DRI3PresentGroup_Release(struct DRI3PresentGroup *This)
  4857. +{
  4858. + ULONG refs = InterlockedDecrement(&This->refs);
  4859. + TRACE("%p decreasing refcount to %u.\n", This, refs);
  4860. + if (refs == 0)
  4861. + {
  4862. + unsigned i;
  4863. + if (This->present_backends)
  4864. + {
  4865. + for (i = 0; i < This->npresent_backends; ++i)
  4866. + {
  4867. + if (This->present_backends[i])
  4868. + DRI3Present_Release(This->present_backends[i]);
  4869. + }
  4870. + HeapFree(GetProcessHeap(), 0, This->present_backends);
  4871. + }
  4872. + HeapFree(GetProcessHeap(), 0, This);
  4873. + }
  4874. + return refs;
  4875. +}
  4876. +
  4877. +static HRESULT WINAPI DRI3PresentGroup_QueryInterface(struct DRI3PresentGroup *This,
  4878. + REFIID riid, void **ppvObject )
  4879. +{
  4880. + if (!ppvObject)
  4881. + return E_POINTER;
  4882. + if (IsEqualGUID(&IID_ID3DPresentGroup, riid) ||
  4883. + IsEqualGUID(&IID_IUnknown, riid))
  4884. + {
  4885. + *ppvObject = This;
  4886. + DRI3PresentGroup_AddRef(This);
  4887. + return S_OK;
  4888. + }
  4889. +
  4890. + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
  4891. + *ppvObject = NULL;
  4892. +
  4893. + return E_NOINTERFACE;
  4894. +}
  4895. +
  4896. +static UINT WINAPI DRI3PresentGroup_GetMultiheadCount(struct DRI3PresentGroup *This)
  4897. +{
  4898. + FIXME("(%p), stub!\n", This);
  4899. + return 1;
  4900. +}
  4901. +
  4902. +static HRESULT WINAPI DRI3PresentGroup_GetPresent(struct DRI3PresentGroup *This,
  4903. + UINT Index, ID3DPresent **ppPresent)
  4904. +{
  4905. + if (Index >= DRI3PresentGroup_GetMultiheadCount(This))
  4906. + {
  4907. + ERR("Index >= MultiHeadCount\n");
  4908. + return D3DERR_INVALIDCALL;
  4909. + }
  4910. + DRI3Present_AddRef(This->present_backends[Index]);
  4911. + *ppPresent = (ID3DPresent *)This->present_backends[Index];
  4912. +
  4913. + return D3D_OK;
  4914. +}
  4915. +
  4916. +static HRESULT WINAPI DRI3PresentGroup_CreateAdditionalPresent(struct DRI3PresentGroup *This,
  4917. + D3DPRESENT_PARAMETERS *pPresentationParameters, ID3DPresent **ppPresent)
  4918. +{
  4919. + HRESULT hr;
  4920. + hr = DRI3Present_new(This->gdi_display, This->present_backends[0]->devname,
  4921. + pPresentationParameters, 0, (struct DRI3Present **)ppPresent,
  4922. + This->ex, This->no_window_changes);
  4923. +
  4924. + return hr;
  4925. +}
  4926. +
  4927. +static void WINAPI DRI3PresentGroup_GetVersion(struct DRI3PresentGroup *This,
  4928. + int *major, int *minor)
  4929. +{
  4930. + *major = WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MAJOR;
  4931. + *minor = WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR;
  4932. +}
  4933. +
  4934. +static ID3DPresentGroupVtbl DRI3PresentGroup_vtable = {
  4935. + (void *)DRI3PresentGroup_QueryInterface,
  4936. + (void *)DRI3PresentGroup_AddRef,
  4937. + (void *)DRI3PresentGroup_Release,
  4938. + (void *)DRI3PresentGroup_GetMultiheadCount,
  4939. + (void *)DRI3PresentGroup_GetPresent,
  4940. + (void *)DRI3PresentGroup_CreateAdditionalPresent,
  4941. + (void *)DRI3PresentGroup_GetVersion
  4942. +};
  4943. +
  4944. +HRESULT present_create_present_group(Display *gdi_display, const WCHAR *device_name,
  4945. + UINT adapter, HWND focus_wnd, D3DPRESENT_PARAMETERS *params,
  4946. + unsigned nparams, ID3DPresentGroup **group, boolean ex, DWORD BehaviorFlags)
  4947. +{
  4948. + struct DRI3PresentGroup *This;
  4949. + DISPLAY_DEVICEW dd;
  4950. + HRESULT hr;
  4951. + unsigned i;
  4952. +
  4953. + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  4954. + sizeof(struct DRI3PresentGroup));
  4955. + if (!This)
  4956. + {
  4957. + ERR("Out of memory.\n");
  4958. + return E_OUTOFMEMORY;
  4959. + }
  4960. +
  4961. + This->gdi_display = gdi_display;
  4962. + This->vtable = &DRI3PresentGroup_vtable;
  4963. + This->refs = 1;
  4964. + This->ex = ex;
  4965. + This->npresent_backends = nparams;
  4966. + This->no_window_changes = !!(BehaviorFlags & D3DCREATE_NOWINDOWCHANGES);
  4967. + This->present_backends = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  4968. + This->npresent_backends * sizeof(struct DRI3Present *));
  4969. + if (!This->present_backends)
  4970. + {
  4971. + DRI3PresentGroup_Release(This);
  4972. + ERR("Out of memory.\n");
  4973. + return E_OUTOFMEMORY;
  4974. + }
  4975. +
  4976. + if (nparams != 1)
  4977. + adapter = 0;
  4978. +
  4979. + for (i = 0; i < This->npresent_backends; ++i)
  4980. + {
  4981. + ZeroMemory(&dd, sizeof(dd));
  4982. + dd.cb = sizeof(dd);
  4983. + /* find final device name */
  4984. + if (!EnumDisplayDevicesW(device_name, adapter + i, &dd, 0))
  4985. + {
  4986. + WARN("Couldn't find subdevice %d from `%s'\n",
  4987. + i, debugstr_w(device_name));
  4988. + }
  4989. +
  4990. + /* create an ID3DPresent for it */
  4991. + hr = DRI3Present_new(gdi_display, dd.DeviceName, &params[i],
  4992. + focus_wnd, &This->present_backends[i], ex, This->no_window_changes);
  4993. + if (FAILED(hr))
  4994. + {
  4995. + DRI3PresentGroup_Release(This);
  4996. + return hr;
  4997. + }
  4998. + }
  4999. +
  5000. + *group = (ID3DPresentGroup *)This;
  5001. + TRACE("Returning %p\n", *group);
  5002. +
  5003. + return D3D_OK;
  5004. +}
  5005. +
  5006. +HRESULT present_create_adapter9(Display *gdi_display, HDC hdc, ID3DAdapter9 **out)
  5007. +{
  5008. + struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
  5009. + HRESULT hr;
  5010. + int fd;
  5011. +
  5012. + if (!d3d9_drm)
  5013. + {
  5014. + ERR("DRM drivers are not supported on your system.\n");
  5015. + return D3DERR_DRIVERINTERNALERROR;
  5016. + }
  5017. +
  5018. + if (ExtEscape(hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
  5019. + sizeof(extesc), (LPSTR)&extesc) <= 0)
  5020. + ERR("X11 drawable lookup failed (hdc=%p)\n", hdc);
  5021. +
  5022. +#ifdef D3D9NINE_DRI2
  5023. + if (!is_dri2_fallback && !DRI3Open(gdi_display, DefaultScreen(gdi_display), &fd))
  5024. +#else
  5025. + if (!DRI3Open(gdi_display, DefaultScreen(gdi_display), &fd))
  5026. +#endif
  5027. + {
  5028. + ERR("DRI3Open failed (fd=%d)\n", fd);
  5029. + return D3DERR_DRIVERINTERNALERROR;
  5030. + }
  5031. +#ifdef D3D9NINE_DRI2
  5032. + if (is_dri2_fallback && !DRI2FallbackOpen(gdi_display, DefaultScreen(gdi_display), &fd))
  5033. + {
  5034. + ERR("DRI2Open failed (fd=%d)\n", fd);
  5035. + return D3DERR_DRIVERINTERNALERROR;
  5036. + }
  5037. +#endif
  5038. + hr = d3d9_drm->create_adapter(fd, out);
  5039. + if (FAILED(hr))
  5040. + {
  5041. + ERR("Unable to create ID3DAdapter9 (fd=%d)\n", fd);
  5042. + return hr;
  5043. + }
  5044. +
  5045. + TRACE("Created ID3DAdapter9 with fd %d\n", fd);
  5046. +
  5047. + return D3D_OK;
  5048. +}
  5049. +
  5050. +BOOL present_has_d3dadapter(Display *gdi_display)
  5051. +{
  5052. + static const void * WINAPI (*pD3DAdapter9GetProc)(const char *);
  5053. + static void *handle = NULL;
  5054. + static int done = 0;
  5055. + HKEY regkey;
  5056. + LSTATUS rc;
  5057. + char *path = NULL;
  5058. +
  5059. + char errbuf[256];
  5060. + char pathbuf[MAX_PATH];
  5061. +
  5062. + /* like in opengl.c (single threaded assumption OK?) */
  5063. + if (done)
  5064. + return handle != NULL;
  5065. + done = 1;
  5066. +
  5067. + if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Direct3DNine", &regkey))
  5068. + {
  5069. + DWORD type;
  5070. + DWORD size = 0;
  5071. +
  5072. + rc = RegQueryValueExA(regkey, "ModulePath", 0, &type, NULL, &size);
  5073. + if (rc == ERROR_FILE_NOT_FOUND)
  5074. + goto use_default_path;
  5075. +
  5076. + TRACE("Reading registry key for module path\n");
  5077. + if (rc != ERROR_SUCCESS || type != REG_SZ)
  5078. + {
  5079. + ERR("Failed to read Direct3DNine ModulePath registry key: Invalid content\n");
  5080. + goto cleanup;
  5081. + }
  5082. +
  5083. + path = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + 1);
  5084. + if (!path)
  5085. + {
  5086. + ERR("Out of memory\n");
  5087. + return FALSE;
  5088. + }
  5089. + rc = RegQueryValueExA(regkey, "ModulePath", 0, &type, (LPBYTE)path, &size);
  5090. + if (rc != ERROR_SUCCESS)
  5091. + {
  5092. + ERR("Failed to read Direct3DNine registry\n");
  5093. + goto cleanup;
  5094. + }
  5095. + /* Split colon separated path for multi-arch support */
  5096. + if (strstr(path, ":"))
  5097. + {
  5098. + char *tmp_path = strstr(path, ":");
  5099. +
  5100. + /* Replace colon by string terminate */
  5101. + *tmp_path = 0;
  5102. + tmp_path ++;
  5103. + handle = wine_dlopen(path,
  5104. + RTLD_GLOBAL | RTLD_NOW, errbuf, sizeof(errbuf));
  5105. + if (!handle)
  5106. + {
  5107. + TRACE("Failed to load '%s': %s\n", path, errbuf);
  5108. +
  5109. + handle = wine_dlopen(tmp_path,
  5110. + RTLD_GLOBAL | RTLD_NOW, errbuf, sizeof(errbuf));
  5111. + if (!handle)
  5112. + {
  5113. + TRACE("Failed to load '%s': %s\n", tmp_path, errbuf);
  5114. + ERR("Failed to load '%s' and '%s' set by ModulePath.\n",
  5115. + path, tmp_path);
  5116. + goto cleanup;
  5117. + }
  5118. + }
  5119. + }
  5120. + else
  5121. + {
  5122. + handle = wine_dlopen(path,
  5123. + RTLD_GLOBAL | RTLD_NOW, errbuf, sizeof(errbuf));
  5124. + if (!handle)
  5125. + {
  5126. + TRACE("Failed to load %s: %s\n", path, errbuf);
  5127. + ERR("Failed to load '%s' set by ModulePath.\n", path);
  5128. + goto cleanup;
  5129. + }
  5130. + }
  5131. + memcpy(pathbuf, path, size >= sizeof(pathbuf) ? (sizeof(pathbuf)-1) : size);
  5132. + pathbuf[sizeof(pathbuf)-1] = 0;
  5133. +
  5134. + HeapFree(GetProcessHeap(), 0, path);
  5135. + }
  5136. +
  5137. +use_default_path:
  5138. +#if !defined(D3D9NINE_MODULEPATH)
  5139. + if (!handle)
  5140. + {
  5141. + ERR("d3d9-nine.dll was built without default module path.\n"
  5142. + "Setting Software\\Wine\\Direct3DNine ModulePath is required\n");
  5143. + goto cleanup;
  5144. + }
  5145. +#else
  5146. + if (!handle)
  5147. + {
  5148. + handle = wine_dlopen(D3D9NINE_MODULEPATH,
  5149. + RTLD_GLOBAL | RTLD_NOW, errbuf, sizeof(errbuf));
  5150. + if (!handle)
  5151. + {
  5152. + ERR("Failed to load '%s': %s\n", D3D9NINE_MODULEPATH, errbuf);
  5153. + goto cleanup;
  5154. + }
  5155. + memcpy(pathbuf, D3D9NINE_MODULEPATH,
  5156. + sizeof(D3D9NINE_MODULEPATH) >= sizeof(pathbuf) ?
  5157. + (sizeof(pathbuf)-1) : sizeof(D3D9NINE_MODULEPATH));
  5158. + pathbuf[sizeof(pathbuf)-1] = 0;
  5159. + }
  5160. +#endif
  5161. + /* find our entry point in d3dadapter9 */
  5162. + pD3DAdapter9GetProc = wine_dlsym(handle, "D3DAdapter9GetProc",
  5163. + errbuf, sizeof(errbuf));
  5164. + if (!pD3DAdapter9GetProc)
  5165. + {
  5166. + ERR("Failed to get the entry point from %s: %s", pathbuf, errbuf);
  5167. + goto cleanup;
  5168. + }
  5169. +
  5170. + /* get a handle to the drm backend struct */
  5171. + d3d9_drm = pD3DAdapter9GetProc("drm");
  5172. + if (!d3d9_drm)
  5173. + {
  5174. + ERR("%s doesn't support the drm backend.\n", pathbuf);
  5175. + goto cleanup;
  5176. + }
  5177. +
  5178. + /* verify that we're binary compatible */
  5179. + if (d3d9_drm->major_version != 0)
  5180. + {
  5181. + ERR("Version mismatch. %s has %d.%d, was expecting 0.x\n",
  5182. + pathbuf, d3d9_drm->major_version, d3d9_drm->minor_version);
  5183. + goto cleanup;
  5184. + }
  5185. +
  5186. + /* this will be used to store d3d_drawables */
  5187. + d3d_hwnd_context = XUniqueContext();
  5188. +
  5189. + if (!PRESENTCheckExtension(gdi_display, 1, 0))
  5190. + {
  5191. + ERR("Unable to query PRESENT.\n");
  5192. + goto cleanup;
  5193. + }
  5194. +
  5195. + if (!DRI3CheckExtension(gdi_display, 1, 0))
  5196. + {
  5197. +#ifndef D3D9NINE_DRI2
  5198. + ERR("Unable to query DRI3.\n");
  5199. + goto cleanup;
  5200. +#else
  5201. + ERR("Unable to query DRI3. Trying DRI2 fallback (slower performance).\n");
  5202. + is_dri2_fallback = 1;
  5203. + if (!DRI2FallbackCheckSupport(gdi_display))
  5204. + {
  5205. + ERR("DRI2 fallback unsupported\n");
  5206. + goto cleanup;
  5207. + }
  5208. +#endif
  5209. + }
  5210. +
  5211. + return TRUE;
  5212. +
  5213. +cleanup:
  5214. + ERR("\033[1;31m\nNative Direct3D 9 will be unavailable."
  5215. + "\nFor more information visit https://wiki.ixit.cz/d3d9\033[0m\n");
  5216. + if (handle)
  5217. + {
  5218. + wine_dlclose(handle, NULL, 0);
  5219. + handle = NULL;
  5220. + }
  5221. +
  5222. + if (path)
  5223. + HeapFree(GetProcessHeap(), 0, path);
  5224. +
  5225. + return FALSE;
  5226. +}
  5227. +
  5228. +BOOL enable_device_vtable_wrapper(void)
  5229. +{
  5230. + if (!d3d9_drm)
  5231. + {
  5232. + ERR("enable_device_vtable_wrapper call before init.\n");
  5233. + return FALSE;
  5234. + }
  5235. + /* Since minor version 1, we can assume a copy of the internal vtable is stored in second pos.
  5236. + * For now always enable if possible the wrapper (enables Steam overlay for example),
  5237. + * we might in the future let user choose. */
  5238. + return d3d9_drm->minor_version >= 1;
  5239. +}
  5240. diff --git a/dlls/d3d9-nine/present.h b/dlls/d3d9-nine/present.h
  5241. new file mode 100644
  5242. index 0000000000..a5516877f1
  5243. --- /dev/null
  5244. +++ b/dlls/d3d9-nine/present.h
  5245. @@ -0,0 +1,40 @@
  5246. +/*
  5247. + * Wine present interface
  5248. + *
  5249. + * Copyright 2015 Patrick Rudolph
  5250. + *
  5251. + * This library is free software; you can redistribute it and/or
  5252. + * modify it under the terms of the GNU Lesser General Public
  5253. + * License as published by the Free Software Foundation; either
  5254. + * version 2.1 of the License, or (at your option) any later version.
  5255. + *
  5256. + * This library is distributed in the hope that it will be useful,
  5257. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5258. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5259. + * Lesser General Public License for more details.
  5260. + *
  5261. + * You should have received a copy of the GNU Lesser General Public
  5262. + * License along with this library; if not, write to the Free Software
  5263. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5264. + */
  5265. +
  5266. +#ifndef __WINE_PRESENT_H
  5267. +#define __WINE_PRESENT_H
  5268. +
  5269. +#ifndef __WINE_CONFIG_H
  5270. +# error You must include config.h to use this header
  5271. +#endif
  5272. +
  5273. +#include <X11/Xlib.h>
  5274. +
  5275. +HRESULT present_create_present_group(Display *gdi_display, const WCHAR *device_name, UINT adapter,
  5276. + HWND focus, D3DPRESENT_PARAMETERS *params, unsigned nparams, ID3DPresentGroup **group,
  5277. + boolean ex, DWORD BehaviorFlags);
  5278. +
  5279. +HRESULT present_create_adapter9(Display *gdi_display, HDC hdc, ID3DAdapter9 **adapter);
  5280. +
  5281. +BOOL present_has_d3dadapter(Display *gdi_display);
  5282. +
  5283. +BOOL enable_device_vtable_wrapper(void);
  5284. +
  5285. +#endif /* __WINE_PRESENT_H */
  5286. diff --git a/dlls/d3d9-nine/shader_validator.c b/dlls/d3d9-nine/shader_validator.c
  5287. new file mode 100644
  5288. index 0000000000..03848b2aa2
  5289. --- /dev/null
  5290. +++ b/dlls/d3d9-nine/shader_validator.c
  5291. @@ -0,0 +1,88 @@
  5292. +/*
  5293. + * Direct3D 9 ShaderValidator
  5294. + *
  5295. + * Copyright 2016 Patrick Rudolph
  5296. + *
  5297. + * This library is free software; you can redistribute it and/or
  5298. + * modify it under the terms of the GNU Lesser General Public
  5299. + * License as published by the Free Software Foundation; either
  5300. + * version 2.1 of the License, or (at your option) any later version.
  5301. + *
  5302. + * This library is distributed in the hope that it will be useful,
  5303. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5304. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5305. + * Lesser General Public License for more details.
  5306. + *
  5307. + * You should have received a copy of the GNU Lesser General Public
  5308. + * License along with this library; if not, write to the Free Software
  5309. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5310. + *
  5311. + */
  5312. +#include "wine/debug.h"
  5313. +WINE_DEFAULT_DEBUG_CHANNEL(d3d9nine);
  5314. +
  5315. +#include "winbase.h"
  5316. +
  5317. +#include "shader_validator.h"
  5318. +
  5319. +static HRESULT WINAPI IDirect3DShaderValidator9Impl_QueryInterface(IDirect3DShaderValidator9Impl *This,
  5320. + REFIID riid, LPVOID* ppobj)
  5321. +{
  5322. + /* TODO: AddRef(iface). */
  5323. + *ppobj = This;
  5324. + TRACE("This=%p, riid=%s, object=%p.\n", This, debugstr_guid(riid), ppobj);
  5325. +
  5326. + return S_OK;
  5327. +}
  5328. +
  5329. +static ULONG WINAPI IDirect3DShaderValidator9Impl_AddRef(IDirect3DShaderValidator9Impl *This)
  5330. +{
  5331. + ULONG ref = InterlockedIncrement(&This->ref);
  5332. + TRACE("This=%p increasing refcount to %u.\n", This, ref);
  5333. +
  5334. + return ref;
  5335. +}
  5336. +
  5337. +static ULONG WINAPI IDirect3DShaderValidator9Impl_Release(IDirect3DShaderValidator9Impl *This)
  5338. +{
  5339. + ULONG ref = InterlockedDecrement(&This->ref);
  5340. + TRACE("This=%p decreasing refcount to %u.\n", This, ref);
  5341. +
  5342. + if (ref == 0)
  5343. + HeapFree(GetProcessHeap(), 0, This);
  5344. +
  5345. + return ref;
  5346. +}
  5347. +
  5348. +static LONG WINAPI IDirect3DShaderValidator9Impl_Begin(IDirect3DShaderValidator9Impl *This,
  5349. + void* callback, void* unknown1, ULONG unknown2)
  5350. +{
  5351. + TRACE("This=%p, callback=%p, unknown1=%p, unknown2=%u\n", This, callback, unknown1, unknown2);
  5352. + return 1;
  5353. +}
  5354. +
  5355. +static LONG WINAPI IDirect3DShaderValidator9Impl_Instruction(IDirect3DShaderValidator9Impl *This,
  5356. + const char* unknown1, unsigned int unknown2, const unsigned long* unknown3, unsigned int unknown4)
  5357. +{
  5358. + TRACE("This=%p, unknown1=%p, unknown2=%u, unknown3=%p, unknown4=%u\n", This, unknown1, unknown2, unknown3, unknown4);
  5359. + return 1;
  5360. +}
  5361. +
  5362. +static LONG WINAPI IDirect3DShaderValidator9Impl_End(IDirect3DShaderValidator9Impl *This)
  5363. +{
  5364. + TRACE("This=%p\n", This);
  5365. + return 1;
  5366. +}
  5367. +
  5368. +const void *IDirect3DShaderValidator9Vtbl[] =
  5369. +{
  5370. + /* IUnknown */
  5371. + IDirect3DShaderValidator9Impl_QueryInterface,
  5372. + IDirect3DShaderValidator9Impl_AddRef,
  5373. + IDirect3DShaderValidator9Impl_Release,
  5374. + /* IDirect3DShaderValidator9 */
  5375. + IDirect3DShaderValidator9Impl_Begin,
  5376. + IDirect3DShaderValidator9Impl_Instruction,
  5377. + IDirect3DShaderValidator9Impl_End
  5378. +};
  5379. +
  5380. diff --git a/dlls/d3d9-nine/shader_validator.h b/dlls/d3d9-nine/shader_validator.h
  5381. new file mode 100644
  5382. index 0000000000..07a5e2d2b4
  5383. --- /dev/null
  5384. +++ b/dlls/d3d9-nine/shader_validator.h
  5385. @@ -0,0 +1,29 @@
  5386. +/*
  5387. + * Direct3D 9 ShaderValidator
  5388. + *
  5389. + * Copyright 2016 Patrick Rudolph
  5390. + *
  5391. + * This library is free software; you can redistribute it and/or
  5392. + * modify it under the terms of the GNU Lesser General Public
  5393. + * License as published by the Free Software Foundation; either
  5394. + * version 2.1 of the License, or (at your option) any later version.
  5395. + *
  5396. + * This library is distributed in the hope that it will be useful,
  5397. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5398. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5399. + * Lesser General Public License for more details.
  5400. + *
  5401. + * You should have received a copy of the GNU Lesser General Public
  5402. + * License along with this library; if not, write to the Free Software
  5403. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5404. + *
  5405. + */
  5406. +
  5407. +typedef struct IDirect3DShaderValidator9Impl
  5408. +{
  5409. + /* IUnknown fields */
  5410. + void *lpVtbl;
  5411. + LONG ref;
  5412. +} IDirect3DShaderValidator9Impl;
  5413. +
  5414. +const void *IDirect3DShaderValidator9Vtbl[6];
  5415. diff --git a/dlls/d3d9-nine/version.rc b/dlls/d3d9-nine/version.rc
  5416. new file mode 100644
  5417. index 0000000000..bfafc2f24a
  5418. --- /dev/null
  5419. +++ b/dlls/d3d9-nine/version.rc
  5420. @@ -0,0 +1,26 @@
  5421. +/*
  5422. + * Copyright 2015 Patrick Rudolph
  5423. + *
  5424. + * This library is free software; you can redistribute it and/or
  5425. + * modify it under the terms of the GNU Lesser General Public
  5426. + * License as published by the Free Software Foundation; either
  5427. + * version 2.1 of the License, or (at your option) any later version.
  5428. + *
  5429. + * This library is distributed in the hope that it will be useful,
  5430. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5431. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5432. + * Lesser General Public License for more details.
  5433. + *
  5434. + * You should have received a copy of the GNU Lesser General Public
  5435. + * License along with this library; if not, write to the Free Software
  5436. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5437. + */
  5438. +
  5439. +#define WINE_FILEDESCRIPTION_STR "Wine Gallium Nine Direct3D"
  5440. +#define WINE_FILENAME_STR "d3d9-nine.dll"
  5441. +#define WINE_FILEVERSION 5,3,1,904
  5442. +#define WINE_FILEVERSION_STR "5.3.1.904"
  5443. +#define WINE_PRODUCTVERSION 5,3,1,904
  5444. +#define WINE_PRODUCTVERSION_STR "5.3.1.904"
  5445. +
  5446. +#include "wine/wine_common_ver.rc"
  5447. diff --git a/dlls/d3d9-nine/wndproc.c b/dlls/d3d9-nine/wndproc.c
  5448. new file mode 100644
  5449. index 0000000000..0ed80de7d7
  5450. --- /dev/null
  5451. +++ b/dlls/d3d9-nine/wndproc.c
  5452. @@ -0,0 +1,277 @@
  5453. +/*
  5454. + * Copyright 2016 Patrick Rudolph
  5455. + *
  5456. + * Based on the file wined3d_main.c taken from wined3d:
  5457. + * All credits go to the original developers:
  5458. + *
  5459. + * Copyright 2002-2003 The wine-d3d team
  5460. + * Copyright 2002-2003 Raphael Junqueira
  5461. + * Copyright 2004 Jason Edmeades
  5462. + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
  5463. + * Copyright 2009 Henri Verbeet for CodeWeavers
  5464. + *
  5465. + * This library is free software; you can redistribute it and/or
  5466. + * modify it under the terms of the GNU Lesser General Public
  5467. + * License as published by the Free Software Foundation; either
  5468. + * version 2.1 of the License, or (at your option) any later version.
  5469. + *
  5470. + * This library is distributed in the hope that it will be useful,
  5471. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5472. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5473. + * Lesser General Public License for more details.
  5474. + *
  5475. + * You should have received a copy of the GNU Lesser General Public
  5476. + * License along with this library; if not, write to the Free Software
  5477. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5478. + */
  5479. +
  5480. +#include "config.h"
  5481. +#include "wine/port.h"
  5482. +
  5483. +#include <stdarg.h>
  5484. +#include <math.h>
  5485. +#include <limits.h>
  5486. +#define NONAMELESSUNION
  5487. +#define NONAMELESSSTRUCT
  5488. +#define COBJMACROS
  5489. +#include "windef.h"
  5490. +#include "winbase.h"
  5491. +#include "winreg.h"
  5492. +#include "wingdi.h"
  5493. +#include "winuser.h"
  5494. +#include "wine/debug.h"
  5495. +#include "wine/unicode.h"
  5496. +
  5497. +#include "wndproc.h"
  5498. +
  5499. +WINE_DEFAULT_DEBUG_CHANNEL(d3dadapter);
  5500. +
  5501. +struct nine_wndproc
  5502. +{
  5503. + HWND window;
  5504. + BOOL unicode;
  5505. + WNDPROC proc;
  5506. + struct DRI3Present *present;
  5507. +};
  5508. +
  5509. +struct nine_wndproc_table
  5510. +{
  5511. + struct nine_wndproc *entries;
  5512. + unsigned int count;
  5513. + unsigned int size;
  5514. +};
  5515. +
  5516. +static struct nine_wndproc_table wndproc_table;
  5517. +
  5518. +static CRITICAL_SECTION nine_wndproc_cs;
  5519. +static CRITICAL_SECTION_DEBUG nine_wndproc_cs_debug =
  5520. +{
  5521. + 0, 0, &nine_wndproc_cs,
  5522. + {&nine_wndproc_cs_debug.ProcessLocksList,
  5523. + &nine_wndproc_cs_debug.ProcessLocksList},
  5524. + 0, 0, {(DWORD_PTR)(__FILE__ ": nine_wndproc_cs")}
  5525. +};
  5526. +static CRITICAL_SECTION nine_wndproc_cs = {&nine_wndproc_cs_debug, -1, 0, 0, 0, 0};
  5527. +
  5528. +BOOL nine_dll_init(HINSTANCE hInstDLL)
  5529. +{
  5530. + WNDCLASSA wc;
  5531. +
  5532. + /* We need our own window class for a fake window which we use to retrieve GL capabilities */
  5533. + /* We might need CS_OWNDC in the future if we notice strange things on Windows.
  5534. + * Various articles/posts about OpenGL problems on Windows recommend this. */
  5535. + wc.style = CS_HREDRAW | CS_VREDRAW;
  5536. + wc.lpfnWndProc = DefWindowProcA;
  5537. + wc.cbClsExtra = 0;
  5538. + wc.cbWndExtra = 0;
  5539. + wc.hInstance = hInstDLL;
  5540. + wc.hIcon = LoadIconA(NULL, (const char *)IDI_WINLOGO);
  5541. + wc.hCursor = LoadCursorA(NULL, (const char *)IDC_ARROW);
  5542. + wc.hbrBackground = NULL;
  5543. + wc.lpszMenuName = NULL;
  5544. + wc.lpszClassName = NINE_WINDOW_CLASS_NAME;
  5545. +
  5546. + if (!RegisterClassA(&wc))
  5547. + {
  5548. + ERR("Failed to register window class '%s'!\n", NINE_WINDOW_CLASS_NAME);
  5549. + return FALSE;
  5550. + }
  5551. +
  5552. + DisableThreadLibraryCalls(hInstDLL);
  5553. +
  5554. + return TRUE;
  5555. +}
  5556. +
  5557. +BOOL nine_dll_destroy(HINSTANCE hInstDLL)
  5558. +{
  5559. + unsigned int i;
  5560. +
  5561. + for (i = 0; i < wndproc_table.count; ++i)
  5562. + {
  5563. + /* Trying to unregister these would be futile. These entries can only
  5564. + * exist if either we skipped them in nine_unregister_window() due
  5565. + * to the application replacing the wndproc after the entry was
  5566. + * registered, or if the application still has an active nine
  5567. + * device. In the latter case the application has bigger problems than
  5568. + * these entries. */
  5569. + WARN("Leftover wndproc table entry %p.\n", &wndproc_table.entries[i]);
  5570. + }
  5571. + HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
  5572. +
  5573. + UnregisterClassA(NINE_WINDOW_CLASS_NAME, hInstDLL);
  5574. +
  5575. + DeleteCriticalSection(&nine_wndproc_cs);
  5576. + return TRUE;
  5577. +}
  5578. +
  5579. +static void nine_wndproc_mutex_lock(void)
  5580. +{
  5581. + EnterCriticalSection(&nine_wndproc_cs);
  5582. +}
  5583. +
  5584. +static void nine_wndproc_mutex_unlock(void)
  5585. +{
  5586. + LeaveCriticalSection(&nine_wndproc_cs);
  5587. +}
  5588. +
  5589. +static struct nine_wndproc *nine_find_wndproc(HWND window)
  5590. +{
  5591. + unsigned int i;
  5592. +
  5593. + for (i = 0; i < wndproc_table.count; ++i)
  5594. + {
  5595. + if (wndproc_table.entries[i].window == window)
  5596. + {
  5597. + return &wndproc_table.entries[i];
  5598. + }
  5599. + }
  5600. +
  5601. + return NULL;
  5602. +}
  5603. +
  5604. +static LRESULT CALLBACK nine_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
  5605. +{
  5606. + struct nine_wndproc *entry;
  5607. + struct DRI3Present *present;
  5608. + BOOL unicode;
  5609. + WNDPROC proc;
  5610. +
  5611. + nine_wndproc_mutex_lock();
  5612. + entry = nine_find_wndproc(window);
  5613. +
  5614. + if (!entry)
  5615. + {
  5616. + nine_wndproc_mutex_unlock();
  5617. + ERR("Window %p is not registered with nine.\n", window);
  5618. + return DefWindowProcW(window, message, wparam, lparam);
  5619. + }
  5620. +
  5621. + present = entry->present;
  5622. + unicode = entry->unicode;
  5623. + proc = entry->proc;
  5624. + nine_wndproc_mutex_unlock();
  5625. +
  5626. + if (present)
  5627. + return device_process_message(present, window, unicode, message, wparam, lparam, proc);
  5628. + if (unicode)
  5629. + return CallWindowProcW(proc, window, message, wparam, lparam);
  5630. + return CallWindowProcA(proc, window, message, wparam, lparam);
  5631. +}
  5632. +
  5633. +BOOL nine_register_window(HWND window, struct DRI3Present *present)
  5634. +{
  5635. + struct nine_wndproc *entry;
  5636. +
  5637. + nine_wndproc_mutex_lock();
  5638. +
  5639. + if (nine_find_wndproc(window))
  5640. + {
  5641. + nine_wndproc_mutex_unlock();
  5642. + WARN("Window %p is already registered with nine.\n", window);
  5643. + return TRUE;
  5644. + }
  5645. +
  5646. + if (wndproc_table.size == wndproc_table.count)
  5647. + {
  5648. + unsigned int new_size = max(1, wndproc_table.size * 2);
  5649. + struct nine_wndproc *new_entries;
  5650. +
  5651. + if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
  5652. + else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
  5653. +
  5654. + if (!new_entries)
  5655. + {
  5656. + nine_wndproc_mutex_unlock();
  5657. + ERR("Failed to grow table.\n");
  5658. + return FALSE;
  5659. + }
  5660. +
  5661. + wndproc_table.entries = new_entries;
  5662. + wndproc_table.size = new_size;
  5663. + }
  5664. +
  5665. + entry = &wndproc_table.entries[wndproc_table.count++];
  5666. + entry->window = window;
  5667. + entry->unicode = IsWindowUnicode(window);
  5668. + /* Set a window proc that matches the window. Some applications (e.g. NoX)
  5669. + * replace the window proc after we've set ours, and expect to be able to
  5670. + * call the previous one (ours) directly, without using CallWindowProc(). */
  5671. + if (entry->unicode)
  5672. + entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)nine_wndproc);
  5673. + else
  5674. + entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)nine_wndproc);
  5675. + entry->present = present;
  5676. +
  5677. + nine_wndproc_mutex_unlock();
  5678. +
  5679. + return TRUE;
  5680. +}
  5681. +
  5682. +BOOL nine_unregister_window(HWND window)
  5683. +{
  5684. + struct nine_wndproc *entry, *last;
  5685. + LONG_PTR proc;
  5686. +
  5687. + nine_wndproc_mutex_lock();
  5688. +
  5689. + if (!(entry = nine_find_wndproc(window)))
  5690. + {
  5691. + nine_wndproc_mutex_unlock();
  5692. + return FALSE;
  5693. + }
  5694. +
  5695. + if (entry->unicode)
  5696. + {
  5697. + proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
  5698. + if (proc != (LONG_PTR)nine_wndproc)
  5699. + {
  5700. + entry->present = NULL;
  5701. + nine_wndproc_mutex_unlock();
  5702. + WARN("Not unregistering window %p, window proc %#lx doesn't match nine window proc %p.\n",
  5703. + window, proc, nine_wndproc);
  5704. + return FALSE;
  5705. + }
  5706. +
  5707. + SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
  5708. + }
  5709. + else
  5710. + {
  5711. + proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
  5712. + if (proc != (LONG_PTR)nine_wndproc)
  5713. + {
  5714. + entry->present = NULL;
  5715. + nine_wndproc_mutex_unlock();
  5716. + WARN("Not unregistering window %p, window proc %#lx doesn't match nine window proc %p.\n",
  5717. + window, proc, nine_wndproc);
  5718. + return FALSE;
  5719. + }
  5720. +
  5721. + SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
  5722. + }
  5723. +
  5724. + last = &wndproc_table.entries[--wndproc_table.count];
  5725. + if (entry != last) *entry = *last;
  5726. +
  5727. + nine_wndproc_mutex_unlock();
  5728. + return TRUE;
  5729. +}
  5730. diff --git a/dlls/d3d9-nine/wndproc.h b/dlls/d3d9-nine/wndproc.h
  5731. new file mode 100644
  5732. index 0000000000..15f26d491a
  5733. --- /dev/null
  5734. +++ b/dlls/d3d9-nine/wndproc.h
  5735. @@ -0,0 +1,41 @@
  5736. +/*
  5737. + * Direct3D wine internal interface main
  5738. + *
  5739. + * Copyright 2002-2003 The wine-d3d team
  5740. + * Copyright 2002-2003 Raphael Junqueira
  5741. + * Copyright 2004 Jason Edmeades
  5742. + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
  5743. + * Copyright 2009 Henri Verbeet for CodeWeavers
  5744. + *
  5745. + * This library is free software; you can redistribute it and/or
  5746. + * modify it under the terms of the GNU Lesser General Public
  5747. + * License as published by the Free Software Foundation; either
  5748. + * version 2.1 of the License, or (at your option) any later version.
  5749. + *
  5750. + * This library is distributed in the hope that it will be useful,
  5751. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5752. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5753. + * Lesser General Public License for more details.
  5754. + *
  5755. + * You should have received a copy of the GNU Lesser General Public
  5756. + * License along with this library; if not, write to the Free Software
  5757. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  5758. + */
  5759. +
  5760. +#ifndef __WINE_NINE_WNDPROC_H
  5761. +#define __WINE_NINE_WNDPROC_H
  5762. +
  5763. +struct DRI3Present;
  5764. +
  5765. +BOOL nine_register_window(HWND window, struct DRI3Present *present);
  5766. +BOOL nine_unregister_window(HWND window);
  5767. +
  5768. +BOOL nine_dll_init(HINSTANCE hInstDLL);
  5769. +BOOL nine_dll_destroy(HINSTANCE hInstDLL);
  5770. +
  5771. +LRESULT device_process_message(struct DRI3Present *present, HWND window, BOOL unicode,
  5772. + UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc);
  5773. +
  5774. +#define NINE_WINDOW_CLASS_NAME "Gallium_Nine_Window"
  5775. +
  5776. +#endif
  5777. --
  5778. 2.15.0