1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774 |
- diff -Naurp Mesa-7.8.1/progs/xdemos/corender.c Mesa-7.8.1.patched/progs/xdemos/corender.c
- --- Mesa-7.8.1/progs/xdemos/corender.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/corender.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,400 @@
- +/**
- + * Example of cooperative rendering into one window by two processes.
- + * The first instance of the program creates the GLX window.
- + * The second instance of the program gets the window ID from the first
- + * and draws into it.
- + * Socket IPC is used for synchronization.
- + *
- + * Usage:
- + * 1. run 'corender &'
- + * 2. run 'corender 2' (any arg will do)
- + *
- + * Brian Paul
- + * 11 Oct 2007
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <assert.h>
- +#include <math.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <X11/keysym.h>
- +#include <unistd.h>
- +#include "ipc.h"
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265358979323846
- +#endif
- +
- +static int MyID = 0; /* 0 or 1 */
- +static int WindowID = 0;
- +static GLXContext Context = 0;
- +static int Width = 700, Height = 350;
- +static int Rot = 0;
- +static int Sock = 0;
- +
- +static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0};
- +static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0};
- +
- +static int Sync = 1; /** synchronized rendering? */
- +
- +
- +static void
- +setup_ipc(void)
- +{
- + int k, port = 10001;
- +
- + if (MyID == 0) {
- + /* I'm the first one, wait for connection from second */
- + k = CreatePort(&port);
- + assert(k != -1);
- +
- + printf("Waiting for connection from another 'corender'\n");
- + Sock = AcceptConnection(k);
- + assert(Sock != -1);
- +
- + printf("Got connection, sending windowID\n");
- +
- + /* send windowID */
- + SendData(Sock, &WindowID, sizeof(WindowID));
- + }
- + else {
- + /* I'm the second one, connect to first */
- + char hostname[1000];
- +
- + MyHostName(hostname, 1000);
- + Sock = Connect(hostname, port);
- + assert(Sock != -1);
- +
- + /* get windowID */
- + ReceiveData(Sock, &WindowID, sizeof(WindowID));
- + printf("Contacted first 'corender', getting WindowID\n");
- + }
- +}
- +
- +
- +
- +/** from GLUT */
- +static void
- +doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
- +{
- + int i, j;
- + GLfloat theta, phi, theta1;
- + GLfloat cosTheta, sinTheta;
- + GLfloat cosTheta1, sinTheta1;
- + GLfloat ringDelta, sideDelta;
- +
- + ringDelta = 2.0 * M_PI / rings;
- + sideDelta = 2.0 * M_PI / nsides;
- +
- + theta = 0.0;
- + cosTheta = 1.0;
- + sinTheta = 0.0;
- + for (i = rings - 1; i >= 0; i--) {
- + theta1 = theta + ringDelta;
- + cosTheta1 = cos(theta1);
- + sinTheta1 = sin(theta1);
- + glBegin(GL_QUAD_STRIP);
- + phi = 0.0;
- + for (j = nsides; j >= 0; j--) {
- + GLfloat cosPhi, sinPhi, dist;
- +
- + phi += sideDelta;
- + cosPhi = cos(phi);
- + sinPhi = sin(phi);
- + dist = R + r * cosPhi;
- +
- + glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
- + glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
- + glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
- + glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
- + }
- + glEnd();
- + theta = theta1;
- + cosTheta = cosTheta1;
- + sinTheta = sinTheta1;
- + }
- +}
- +
- +
- +static void
- +redraw(Display *dpy)
- +{
- + int dbg = 0;
- +
- + glXMakeCurrent(dpy, WindowID, Context);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- + glClearColor(0.5, 0.5, 0.5, 0.0);
- +
- + if (MyID == 0) {
- + /* First process */
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glTranslatef(-1, 0, 0);
- + glRotatef(Rot, 1, 0, 0);
- + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
- + doughnut(0.5, 2.0, 20, 30);
- + glPopMatrix();
- +
- + glFinish();
- + if (!Sync) {
- + usleep(1000*10);
- + }
- +
- + /* signal second process to render */
- + if (Sync) {
- + int code = 1;
- + if (dbg) printf("0: send signal\n");
- + SendData(Sock, &code, sizeof(code));
- + SendData(Sock, &Rot, sizeof(Rot));
- + }
- +
- + /* wait for second process to finish rendering */
- + if (Sync) {
- + int code = 0;
- + if (dbg) printf("0: wait signal\n");
- + ReceiveData(Sock, &code, sizeof(code));
- + if (dbg) printf("0: got signal\n");
- + assert(code == 2);
- + }
- +
- + }
- + else {
- + /* Second process */
- +
- + /* wait for first process's signal for me to render */
- + if (Sync) {
- + int code = 0;
- + if (dbg) printf("1: wait signal\n");
- + ReceiveData(Sock, &code, sizeof(code));
- + ReceiveData(Sock, &Rot, sizeof(Rot));
- +
- + if (dbg) printf("1: got signal\n");
- + assert(code == 1);
- + }
- +
- + /* XXX this clear should not be here, but for some reason, it
- + * makes things _mostly_ work correctly w/ NVIDIA's driver.
- + * There's only occasional glitches.
- + * Without this glClear(), depth buffer for the second process
- + * is pretty much broken.
- + */
- + /* glClear(GL_DEPTH_BUFFER_BIT); */
- +
- + glPushMatrix();
- + glTranslatef(1, 0, 0);
- + glRotatef(Rot + 90 , 1, 0, 0);
- + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
- + doughnut(0.5, 2.0, 20, 30);
- + glPopMatrix();
- + glFinish();
- +
- + glXSwapBuffers(dpy, WindowID);
- + usleep(1000*10);
- +
- + /* signal first process that I'm done rendering */
- + if (Sync) {
- + int code = 2;
- + if (dbg) printf("1: send signal\n");
- + SendData(Sock, &code, sizeof(code));
- + }
- + }
- +}
- +
- +
- +static void
- +resize(Display *dpy, int width, int height)
- +{
- + float ar = (float) width / height;
- +
- + glXMakeCurrent(dpy, WindowID, Context);
- +
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0, 0, -15);
- +
- + Width = width;
- + Height = height;
- +}
- +
- +
- +
- +static void
- +set_window_title(Display *dpy, Window win, const char *title)
- +{
- + XSizeHints sizehints;
- + sizehints.flags = 0;
- + XSetStandardProperties(dpy, win, title, title,
- + None, (char **)NULL, 0, &sizehints);
- +}
- +
- +
- +static Window
- +make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
- +{
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + int x = 0, y = 0;
- + char *name = NULL;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, x, y, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + return win;
- +}
- +
- +
- +static void
- +set_event_mask(Display *dpy, Window win)
- +{
- + XSetWindowAttributes attr;
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
- +}
- +
- +
- +static void
- +event_loop(Display *dpy)
- +{
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- +
- + switch (event.type) {
- + case Expose:
- + redraw(dpy);
- + break;
- + case ConfigureNotify:
- + resize(dpy, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + exit(0);
- + }
- + }
- + }
- + default:
- + /* nothing */
- + ;
- + }
- + }
- +
- + if (MyID == 0 || !Sync)
- + Rot += 1;
- + redraw(dpy);
- + }
- +}
- +
- +
- +static XVisualInfo *
- +choose_visual(Display *dpy)
- +{
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum = DefaultScreen( dpy );
- + return glXChooseVisual(dpy, scrnum, attribs);
- +}
- +
- +
- +static void
- +parse_opts(int argc, char *argv[])
- +{
- + if (argc > 1) {
- + MyID = 1;
- + }
- +}
- +
- +
- +int
- +main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + XVisualInfo *visinfo;
- +
- + parse_opts(argc, argv);
- +
- + dpy = XOpenDisplay(NULL);
- +
- + visinfo = choose_visual(dpy);
- +
- + Context = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!Context) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + if (MyID == 0) {
- + WindowID = make_gl_window(dpy, visinfo, Width, Height);
- + set_window_title(dpy, WindowID, "corender");
- + XMapWindow(dpy, WindowID);
- + /*printf("WindowID 0x%x\n", (int) WindowID);*/
- + }
- +
- + /* do ipc hand-shake here */
- + setup_ipc();
- + assert(Sock);
- + assert(WindowID);
- +
- + if (MyID == 1) {
- + set_event_mask(dpy, WindowID);
- + }
- +
- + resize(dpy, Width, Height);
- +
- + event_loop(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glsync.c Mesa-7.8.1.patched/progs/xdemos/glsync.c
- --- Mesa-7.8.1/progs/xdemos/glsync.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glsync.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,295 @@
- +/*
- + * Copyright © 2007 Intel Corporation
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice (including the next
- + * paragraph) shall be included in all copies or substantial portions of the
- + * Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- + * IN THE SOFTWARE.
- + *
- + * Authors:
- + * Jesse Barnes <jesse.barnes@intel.com>
- + *
- + */
- +
- +/** @file glsync.c
- + * The program is simple: it paints a window alternating colors (red &
- + * white) either as fast as possible or synchronized to vblank events
- + *
- + * If run normally, the program should display a window that exhibits
- + * significant tearing between red and white colors (e.g. you might get
- + * a "waterfall" effect of red and white horizontal bars).
- + *
- + * If run with the '-s b' option, the program should synchronize the
- + * window color changes with the vertical blank period, resulting in a
- + * window that looks orangish with a high frequency flicker (which may
- + * be invisible). If the window is moved to another screen, this
- + * property should be preserved. If the window spans two screens, it
- + * shouldn't tear on whichever screen most of the window is on; the
- + * portion on the other screen may show some tearing (like the
- + * waterfall effect above).
- + *
- + * Other options include '-w <width>' and '-h <height' to set the
- + * window size.
- + */
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <GL/gl.h>
- +#include <GL/glu.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +#include <X11/X.h>
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +
- +void (*video_sync_get)();
- +void (*video_sync)();
- +void (*swap_interval)();
- +
- +static int GLXExtensionSupported(Display *dpy, const char *extension)
- +{
- + const char *extensionsString, *pos;
- +
- + extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
- +
- + pos = strstr(extensionsString, extension);
- +
- + if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
- + (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
- + return 1;
- +
- + return 0;
- +}
- +
- +extern char *optarg;
- +extern int optind, opterr, optopt;
- +static char optstr[] = "w:h:s:vi:";
- +
- +enum sync_type {
- + none = 0,
- + sgi_video_sync,
- + buffer_swap
- +};
- +
- +static void usage(char *name)
- +{
- + printf("usage: %s [-w <width>] [-h <height>] [-s<sync method>] "
- + "[-v]\n", name);
- + printf("\t-s<sync method>:\n");
- + printf("\t\tn: none\n");
- + printf("\t\ts: SGI video sync extension\n");
- + printf("\t\tb: buffer swap\n");
- + printf("\t-i<swap interval>\n");
- + printf("\t-v: verbose (print count)\n");
- + exit(-1);
- +}
- +
- +int main(int argc, char *argv[])
- +{
- + Display *disp;
- + XVisualInfo *pvi;
- + XSetWindowAttributes swa;
- + GLint last_val = -1, count = 0;
- + Window winGL;
- + GLXContext context;
- + int dummy;
- + Atom wmDelete;
- + enum sync_type waitforsync = none;
- + int width = 500, height = 500, verbose = 0, interval = 1;
- + int c, i = 1;
- + int ret;
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + None };
- + int db_attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + XSizeHints sizehints;
- +
- + opterr = 0;
- + while ((c = getopt(argc, argv, optstr)) != -1) {
- + switch (c) {
- + case 'w':
- + width = atoi(optarg);
- + break;
- + case 'h':
- + height = atoi(optarg);
- + break;
- + case 's':
- + switch (optarg[0]) {
- + case 'n':
- + waitforsync = none;
- + break;
- + case 's':
- + waitforsync = sgi_video_sync;
- + break;
- + case 'b':
- + waitforsync = buffer_swap;
- + break;
- + default:
- + usage(argv[0]);
- + break;
- + }
- + break;
- + case 'v':
- + verbose = 1;
- + break;
- + case 'i':
- + interval = atoi(optarg);
- + break;
- + default:
- + usage(argv[0]);
- + break;
- + }
- + }
- +
- + disp = XOpenDisplay(NULL);
- + if (!disp) {
- + fprintf(stderr, "failed to open display\n");
- + return -1;
- + }
- +
- + if (!glXQueryExtension(disp, &dummy, &dummy)) {
- + fprintf(stderr, "glXQueryExtension failed\n");
- + return -1;
- + }
- +
- + if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) {
- + fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n");
- + return -1;
- + }
- +
- + if (waitforsync != buffer_swap) {
- + pvi = glXChooseVisual(disp, DefaultScreen(disp), attribs);
- + } else {
- + pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs);
- + }
- +
- + if (!pvi) {
- + fprintf(stderr, "failed to choose visual, exiting\n");
- + return -1;
- + }
- +
- + pvi->screen = DefaultScreen(disp);
- +
- + swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
- + pvi->visual, AllocNone);
- + swa.border_pixel = 0;
- + swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
- + StructureNotifyMask;
- + winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
- + 0, 0,
- + width, height,
- + 0, pvi->depth, InputOutput, pvi->visual,
- + CWBorderPixel | CWColormap | CWEventMask, &swa);
- + if (!winGL) {
- + fprintf(stderr, "window creation failed\n");
- + return -1;
- + }
- + wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
- + XSetWMProtocols(disp, winGL, &wmDelete, 1);
- +
- + sizehints.x = 0;
- + sizehints.y = 0;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- +
- + XSetNormalHints(disp, winGL, &sizehints);
- + XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
- + None, NULL, 0, &sizehints);
- +
- + context = glXCreateContext(disp, pvi, NULL, GL_TRUE);
- + if (!context) {
- + fprintf(stderr, "failed to create glx context\n");
- + return -1;
- + }
- +
- + XMapWindow(disp, winGL);
- + ret = glXMakeCurrent(disp, winGL, context);
- + if (!ret) {
- + fprintf(stderr, "failed to make context current: %d\n", ret);
- + }
- +
- + video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI");
- + video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI");
- +
- + swap_interval = glXGetProcAddress((unsigned char *)"glXSwapIntervalSGI");
- +
- + if (!video_sync_get || !video_sync || !swap_interval) {
- + fprintf(stderr, "failed to get sync functions\n");
- + return -1;
- + }
- +
- + if (waitforsync == buffer_swap) {
- + swap_interval(interval);
- + fprintf(stderr, "set swap interval to %d\n", interval);
- + }
- + video_sync_get(&count);
- + count++;
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- + while (i++) {
- + /* Alternate colors to make tearing obvious */
- + if (i & 1) {
- + glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- + glColor3f(1.0f, 1.0f, 1.0f);
- + } else {
- + glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
- + glColor3f(1.0f, 0.0f, 0.0f);
- + }
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- + glRectf(0, 0, width, height);
- +
- + /* Wait for vsync */
- + if (waitforsync == sgi_video_sync) {
- + if (verbose)
- + fprintf(stderr, "waiting on count %d\n", count);
- + video_sync(2, (count + 1) % 2, &count);
- + if (count < last_val)
- + fprintf(stderr, "error: vblank count went backwards: %d -> %d\n", last_val, count);
- + if (count == last_val)
- + fprintf(stderr, "error: count didn't change: %d\n", count);
- + last_val = count;
- + glFlush();
- + } else if (waitforsync == buffer_swap) {
- + glXSwapBuffers(disp, winGL);
- + } else {
- + video_sync_get(&count);
- + sleep(1);
- + glFinish();
- + }
- +
- + if (verbose) {
- + video_sync_get(&count);
- + fprintf(stderr, "current count: %d\n", count);
- + }
- + }
- +
- + XDestroyWindow(disp, winGL);
- + glXDestroyContext(disp, context);
- + XCloseDisplay(disp);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glthreads.c Mesa-7.8.1.patched/progs/xdemos/glthreads.c
- --- Mesa-7.8.1/progs/xdemos/glthreads.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glthreads.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,716 @@
- +/*
- + * Copyright (C) 2000 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * This program tests GLX thread safety.
- + * Command line options:
- + * -p Open a display connection for each thread
- + * -l Enable application-side locking
- + * -n <num threads> Number of threads to create (default is 2)
- + * -display <display name> Specify X display (default is $DISPLAY)
- + * -t Use texture mapping
- + *
- + * Brian Paul 20 July 2000
- + */
- +
- +
- +/*
- + * Notes:
- + * - Each thread gets its own GLX context.
- + *
- + * - The GLX contexts share texture objects.
- + *
- + * - When 't' is pressed to update the texture image, the window/thread which
- + * has input focus is signalled to change the texture. The other threads
- + * should see the updated texture the next time they call glBindTexture.
- + */
- +
- +
- +#if defined(PTHREADS) /* defined by Mesa on Linux and other platforms */
- +
- +#include <assert.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <math.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <pthread.h>
- +
- +
- +/*
- + * Each window/thread/context:
- + */
- +struct winthread {
- + Display *Dpy;
- + int Index;
- + pthread_t Thread;
- + Window Win;
- + GLXContext Context;
- + float Angle;
- + int WinWidth, WinHeight;
- + GLboolean NewSize;
- + GLboolean Initialized;
- + GLboolean MakeNewTexture;
- +};
- +
- +
- +#define MAX_WINTHREADS 100
- +static struct winthread WinThreads[MAX_WINTHREADS];
- +static int NumWinThreads = 0;
- +static volatile GLboolean ExitFlag = GL_FALSE;
- +
- +static GLboolean MultiDisplays = 0;
- +static GLboolean Locking = 0;
- +static GLboolean Texture = GL_FALSE;
- +static GLuint TexObj = 12;
- +static GLboolean Animate = GL_TRUE;
- +
- +static pthread_mutex_t Mutex;
- +static pthread_cond_t CondVar;
- +static pthread_mutex_t CondMutex;
- +
- +
- +static void
- +Error(const char *msg)
- +{
- + fprintf(stderr, "Error: %s\n", msg);
- + exit(1);
- +}
- +
- +
- +static void
- +signal_redraw(void)
- +{
- + pthread_mutex_lock(&CondMutex);
- + pthread_cond_broadcast(&CondVar);
- + pthread_mutex_unlock(&CondMutex);
- +}
- +
- +
- +static void
- +MakeNewTexture(struct winthread *wt)
- +{
- +#define TEX_SIZE 128
- + static float step = 0.0;
- + GLfloat image[TEX_SIZE][TEX_SIZE][4];
- + GLint width;
- + int i, j;
- +
- + for (j = 0; j < TEX_SIZE; j++) {
- + for (i = 0; i < TEX_SIZE; i++) {
- + float dt = 5.0 * (j - 0.5 * TEX_SIZE) / TEX_SIZE;
- + float ds = 5.0 * (i - 0.5 * TEX_SIZE) / TEX_SIZE;
- + float r = dt * dt + ds * ds + step;
- + image[j][i][0] =
- + image[j][i][1] =
- + image[j][i][2] = 0.75 + 0.25 * cos(r);
- + image[j][i][3] = 1.0;
- + }
- + }
- +
- + step += 0.5;
- +
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- +
- + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
- + if (width) {
- + assert(width == TEX_SIZE);
- + /* sub-tex replace */
- + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEX_SIZE, TEX_SIZE,
- + GL_RGBA, GL_FLOAT, image);
- + }
- + else {
- + /* create new */
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- +
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
- + GL_RGBA, GL_FLOAT, image);
- + }
- +}
- +
- +
- +
- +/* draw a colored cube */
- +static void
- +draw_object(void)
- +{
- + glPushMatrix();
- + glScalef(0.75, 0.75, 0.75);
- +
- + glColor3f(1, 0, 0);
- +
- + if (Texture) {
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + glEnable(GL_TEXTURE_2D);
- + }
- + else {
- + glDisable(GL_TEXTURE_2D);
- + }
- +
- + glBegin(GL_QUADS);
- +
- + /* -X */
- + glColor3f(0, 1, 1);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
- +
- + /* +X */
- + glColor3f(1, 0, 0);
- + glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
- +
- + /* -Y */
- + glColor3f(1, 0, 1);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
- +
- + /* +Y */
- + glColor3f(0, 1, 0);
- + glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
- +
- + /* -Z */
- + glColor3f(1, 1, 0);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
- +
- + /* +Y */
- + glColor3f(0, 0, 1);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
- +
- + glEnd();
- +
- + glPopMatrix();
- +}
- +
- +
- +/* signal resize of given window */
- +static void
- +resize(struct winthread *wt, int w, int h)
- +{
- + wt->NewSize = GL_TRUE;
- + wt->WinWidth = w;
- + wt->WinHeight = h;
- + if (!Animate)
- + signal_redraw();
- +}
- +
- +
- +/*
- + * We have an instance of this for each thread.
- + */
- +static void
- +draw_loop(struct winthread *wt)
- +{
- + while (!ExitFlag) {
- +
- + if (Locking)
- + pthread_mutex_lock(&Mutex);
- +
- + glXMakeCurrent(wt->Dpy, wt->Win, wt->Context);
- + if (!wt->Initialized) {
- + printf("glthreads: %d: GL_RENDERER = %s\n", wt->Index,
- + (char *) glGetString(GL_RENDERER));
- + if (Texture /*&& wt->Index == 0*/) {
- + MakeNewTexture(wt);
- + }
- + wt->Initialized = GL_TRUE;
- + }
- +
- + if (Locking)
- + pthread_mutex_unlock(&Mutex);
- +
- + glEnable(GL_DEPTH_TEST);
- +
- + if (wt->NewSize) {
- + GLfloat w = (float) wt->WinWidth / (float) wt->WinHeight;
- + glViewport(0, 0, wt->WinWidth, wt->WinHeight);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-w, w, -1.0, 1.0, 1.5, 10);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0, 0, -2.5);
- + wt->NewSize = GL_FALSE;
- + }
- +
- + if (wt->MakeNewTexture) {
- + MakeNewTexture(wt);
- + wt->MakeNewTexture = GL_FALSE;
- + }
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(wt->Angle, 0, 1, 0);
- + glRotatef(wt->Angle, 1, 0, 0);
- + glScalef(0.7, 0.7, 0.7);
- + draw_object();
- + glPopMatrix();
- +
- + if (Locking)
- + pthread_mutex_lock(&Mutex);
- +
- + glXSwapBuffers(wt->Dpy, wt->Win);
- +
- + if (Locking)
- + pthread_mutex_unlock(&Mutex);
- +
- + if (Animate) {
- + usleep(5000);
- + }
- + else {
- + /* wait for signal to draw */
- + pthread_mutex_lock(&CondMutex);
- + pthread_cond_wait(&CondVar, &CondMutex);
- + pthread_mutex_unlock(&CondMutex);
- + }
- + wt->Angle += 1.0;
- + }
- +}
- +
- +
- +static void
- +keypress(XEvent *event, struct winthread *wt)
- +{
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- +
- + XLookupString(&event->xkey, buf, sizeof(buf), &keySym, &stat);
- +
- + switch (keySym) {
- + case XK_Escape:
- + /* tell all threads to exit */
- + if (!Animate) {
- + signal_redraw();
- + }
- + ExitFlag = GL_TRUE;
- + /*printf("exit draw_loop %d\n", wt->Index);*/
- + return;
- + case XK_t:
- + case XK_T:
- + if (Texture) {
- + wt->MakeNewTexture = GL_TRUE;
- + if (!Animate)
- + signal_redraw();
- + }
- + break;
- + case XK_a:
- + case XK_A:
- + Animate = !Animate;
- + if (Animate) /* yes, prev Animate state! */
- + signal_redraw();
- + break;
- + case XK_s:
- + case XK_S:
- + if (!Animate)
- + signal_redraw();
- + break;
- + default:
- + ; /* nop */
- + }
- +}
- +
- +
- +/*
- + * The main process thread runs this loop.
- + * Single display connection for all threads.
- + */
- +static void
- +event_loop(Display *dpy)
- +{
- + XEvent event;
- + int i;
- +
- + assert(!MultiDisplays);
- +
- + while (!ExitFlag) {
- +
- + if (Locking) {
- + while (1) {
- + int k;
- + pthread_mutex_lock(&Mutex);
- + k = XPending(dpy);
- + if (k) {
- + XNextEvent(dpy, &event);
- + pthread_mutex_unlock(&Mutex);
- + break;
- + }
- + pthread_mutex_unlock(&Mutex);
- + usleep(5000);
- + }
- + }
- + else {
- + XNextEvent(dpy, &event);
- + }
- +
- + switch (event.type) {
- + case ConfigureNotify:
- + /* Find winthread for this event's window */
- + for (i = 0; i < NumWinThreads; i++) {
- + struct winthread *wt = &WinThreads[i];
- + if (event.xconfigure.window == wt->Win) {
- + resize(wt, event.xconfigure.width,
- + event.xconfigure.height);
- + break;
- + }
- + }
- + break;
- + case KeyPress:
- + for (i = 0; i < NumWinThreads; i++) {
- + struct winthread *wt = &WinThreads[i];
- + if (event.xkey.window == wt->Win) {
- + keypress(&event, wt);
- + break;
- + }
- + }
- + break;
- + default:
- + /*no-op*/ ;
- + }
- + }
- +}
- +
- +
- +/*
- + * Separate display connection for each thread.
- + */
- +static void
- +event_loop_multi(void)
- +{
- + XEvent event;
- + int w = 0;
- +
- + assert(MultiDisplays);
- +
- + while (!ExitFlag) {
- + struct winthread *wt = &WinThreads[w];
- + if (XPending(wt->Dpy)) {
- + XNextEvent(wt->Dpy, &event);
- + switch (event.type) {
- + case ConfigureNotify:
- + resize(wt, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + keypress(&event, wt);
- + break;
- + default:
- + ; /* nop */
- + }
- + }
- + w = (w + 1) % NumWinThreads;
- + usleep(5000);
- + }
- +}
- +
- +
- +
- +/*
- + * we'll call this once for each thread, before the threads are created.
- + */
- +static void
- +create_window(struct winthread *wt, GLXContext shareCtx)
- +{
- + Window win;
- + GLXContext ctx;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + XVisualInfo *visinfo;
- + int width = 160, height = 160;
- + int xpos = (wt->Index % 8) * (width + 10);
- + int ypos = (wt->Index / 8) * (width + 20);
- +
- + scrnum = DefaultScreen(wt->Dpy);
- + root = RootWindow(wt->Dpy, scrnum);
- +
- + visinfo = glXChooseVisual(wt->Dpy, scrnum, attrib);
- + if (!visinfo) {
- + Error("Unable to find RGB, Z, double-buffered visual");
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(wt->Dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(wt->Dpy, root, xpos, ypos, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (!win) {
- + Error("Couldn't create window");
- + }
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(wt->Dpy, win, &sizehints);
- + XSetStandardProperties(wt->Dpy, win, "glthreads", "glthreads",
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + ctx = glXCreateContext(wt->Dpy, visinfo, shareCtx, True);
- + if (!ctx) {
- + Error("Couldn't create GLX context");
- + }
- +
- + XMapWindow(wt->Dpy, win);
- + XSync(wt->Dpy, 0);
- +
- + /* save the info for this window/context */
- + wt->Win = win;
- + wt->Context = ctx;
- + wt->Angle = 0.0;
- + wt->WinWidth = width;
- + wt->WinHeight = height;
- + wt->NewSize = GL_TRUE;
- +}
- +
- +
- +/*
- + * Called by pthread_create()
- + */
- +static void *
- +thread_function(void *p)
- +{
- + struct winthread *wt = (struct winthread *) p;
- + draw_loop(wt);
- + return NULL;
- +}
- +
- +
- +/*
- + * called before exit to wait for all threads to finish
- + */
- +static void
- +clean_up(void)
- +{
- + int i;
- +
- + /* wait for threads to finish */
- + for (i = 0; i < NumWinThreads; i++) {
- + pthread_join(WinThreads[i].Thread, NULL);
- + }
- +
- + for (i = 0; i < NumWinThreads; i++) {
- + glXDestroyContext(WinThreads[i].Dpy, WinThreads[i].Context);
- + XDestroyWindow(WinThreads[i].Dpy, WinThreads[i].Win);
- + }
- +}
- +
- +
- +static void
- +usage(void)
- +{
- + printf("glthreads: test of GL thread safety (any key = exit)\n");
- + printf("Usage:\n");
- + printf(" glthreads [options]\n");
- + printf("Options:\n");
- + printf(" -display DISPLAYNAME Specify display string\n");
- + printf(" -n NUMTHREADS Number of threads to create\n");
- + printf(" -p Use a separate display connection for each thread\n");
- + printf(" -l Use application-side locking\n");
- + printf(" -t Enable texturing\n");
- + printf("Keyboard:\n");
- + printf(" Esc Exit\n");
- + printf(" t Change texture image (requires -t option)\n");
- + printf(" a Toggle animation\n");
- + printf(" s Step rotation (when not animating)\n");
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + char *displayName = NULL;
- + int numThreads = 2;
- + Display *dpy = NULL;
- + int i;
- + Status threadStat;
- +
- + if (argc == 1) {
- + usage();
- + }
- + else {
- + int i;
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
- + displayName = argv[i + 1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-p") == 0) {
- + MultiDisplays = 1;
- + }
- + else if (strcmp(argv[i], "-l") == 0) {
- + Locking = 1;
- + }
- + else if (strcmp(argv[i], "-t") == 0) {
- + Texture = 1;
- + }
- + else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) {
- + numThreads = atoi(argv[i + 1]);
- + if (numThreads < 1)
- + numThreads = 1;
- + else if (numThreads > MAX_WINTHREADS)
- + numThreads = MAX_WINTHREADS;
- + i++;
- + }
- + else {
- + usage();
- + exit(1);
- + }
- + }
- + }
- +
- + if (Locking)
- + printf("glthreads: Using explicit locks around Xlib calls.\n");
- + else
- + printf("glthreads: No explict locking.\n");
- +
- + if (MultiDisplays)
- + printf("glthreads: Per-thread display connections.\n");
- + else
- + printf("glthreads: Single display connection.\n");
- +
- + /*
- + * VERY IMPORTANT: call XInitThreads() before any other Xlib functions.
- + */
- + if (!MultiDisplays) {
- + if (!Locking) {
- + threadStat = XInitThreads();
- + if (threadStat) {
- + printf("XInitThreads() returned %d (success)\n", (int) threadStat);
- + }
- + else {
- + printf("XInitThreads() returned 0 (failure- this program may fail)\n");
- + }
- + }
- +
- + dpy = XOpenDisplay(displayName);
- + if (!dpy) {
- + fprintf(stderr, "Unable to open display %s\n", XDisplayName(displayName));
- + return -1;
- + }
- + }
- +
- + pthread_mutex_init(&Mutex, NULL);
- + pthread_mutex_init(&CondMutex, NULL);
- + pthread_cond_init(&CondVar, NULL);
- +
- + printf("glthreads: creating windows\n");
- +
- + NumWinThreads = numThreads;
- +
- + /* Create the GLX windows and contexts */
- + for (i = 0; i < numThreads; i++) {
- + GLXContext share;
- +
- + if (MultiDisplays) {
- + WinThreads[i].Dpy = XOpenDisplay(displayName);
- + assert(WinThreads[i].Dpy);
- + }
- + else {
- + WinThreads[i].Dpy = dpy;
- + }
- + WinThreads[i].Index = i;
- + WinThreads[i].Initialized = GL_FALSE;
- +
- + share = (Texture && i > 0) ? WinThreads[0].Context : 0;
- +
- + create_window(&WinThreads[i], share);
- + }
- +
- + printf("glthreads: creating threads\n");
- +
- + /* Create the threads */
- + for (i = 0; i < numThreads; i++) {
- + pthread_create(&WinThreads[i].Thread, NULL, thread_function,
- + (void*) &WinThreads[i]);
- + printf("glthreads: Created thread %p\n", (void *) WinThreads[i].Thread);
- + }
- +
- + if (MultiDisplays)
- + event_loop_multi();
- + else
- + event_loop(dpy);
- +
- + clean_up();
- +
- + if (MultiDisplays) {
- + for (i = 0; i < numThreads; i++) {
- + XCloseDisplay(WinThreads[i].Dpy);
- + }
- + }
- + else {
- + XCloseDisplay(dpy);
- + }
- +
- + return 0;
- +}
- +
- +
- +#else /* PTHREADS */
- +
- +
- +#include <stdio.h>
- +
- +int
- +main(int argc, char *argv[])
- +{
- + printf("Sorry, this program wasn't compiled with PTHREADS defined.\n");
- + return 0;
- +}
- +
- +
- +#endif /* PTHREADS */
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxcontexts.c Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c
- --- Mesa-7.8.1/progs/xdemos/glxcontexts.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,548 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/*
- + * Version of glxgears that creates/destroys the rendering context for each
- + * frame. Also periodically destroy/recreate the window.
- + * Good for finding memory leaks, etc.
- + *
- + * Command line options:
- + * -info print GL implementation information
- + *
- + */
- +
- +
- +#include <assert.h>
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +
- +
- +#define BENCHMARK
- +
- +#ifdef BENCHMARK
- +
- +/* XXX this probably isn't very portable */
- +
- +#include <sys/time.h>
- +#include <unistd.h>
- +
- +/* return current time (in seconds) */
- +static double
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
- +}
- +
- +#else /*BENCHMARK*/
- +
- +/* dummy */
- +static double
- +current_time(void)
- +{
- + /* update this function for other platforms! */
- + static double t = 0.0;
- + static int warn = 1;
- + if (warn) {
- + fprintf(stderr, "Warning: current_time() not implemented!!\n");
- + warn = 0;
- + }
- + return t += 1.0;
- +}
- +
- +#endif /*BENCHMARK*/
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
- +static GLint gear1, gear2, gear3;
- +static GLfloat angle = 0.0;
- +
- +static XVisualInfo *visinfo = NULL;
- +static int WinWidth = 300, WinHeight = 300;
- +
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +do_draw(void)
- +{
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + glPushMatrix();
- + glTranslatef(-3.0, -2.0, 0.0);
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(3.1, -2.0, 0.0);
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(-3.1, 4.2, 0.0);
- + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
- + glCallList(gear3);
- + glPopMatrix();
- +
- + glPopMatrix();
- +}
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(int width, int height)
- +{
- + glViewport(0, 0, (GLint) width, (GLint) height);
- +
- + {
- + GLfloat h = (GLfloat) height / (GLfloat) width;
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- + }
- +
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -40.0);
- +}
- +
- +
- +static void
- +init(void)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
- + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_CULL_FACE);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + /* make the gears */
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(0.5, 2.0, 2.0, 10, 0.7);
- + glEndList();
- +
- + gear3 = glGenLists(1);
- + glNewList(gear3, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
- + gear(1.3, 2.0, 0.5, 10, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- +}
- +
- +
- +static void
- +draw( Display *dpy, Window win )
- +{
- + GLXContext ctx;
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + glXMakeCurrent(dpy, win, ctx);
- +
- + init();
- +
- + reshape(WinWidth, WinHeight);
- +
- + do_draw();
- +
- + glDeleteLists(gear1, 1);
- + glDeleteLists(gear2, 1);
- + glDeleteLists(gear3, 1);
- +
- + glXSwapBuffers(dpy, win);
- + glXDestroyContext(dpy, ctx);
- +}
- +
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height,
- + Window *winRet)
- +{
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + if (visinfo)
- + XFree(visinfo);
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attribs );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + attr.override_redirect = 0;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
- +
- + win = XCreateWindow( dpy, root, x, y, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + *winRet = win;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy)
- +{
- + Window win;
- + make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win);
- + XMapWindow(dpy, win);
- +
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + /* we'll redraw below */
- + break;
- + case ConfigureNotify:
- + WinWidth = event.xconfigure.width;
- + WinHeight = event.xconfigure.height;
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- + }
- + }
- + }
- + }
- + }
- +
- + {
- + static int frames = 0;
- + static double tRot0 = -1.0, tRate0 = -1.0;
- + double dt, t = current_time();
- + if (tRot0 < 0.0)
- + tRot0 = t;
- + dt = t - tRot0;
- + tRot0 = t;
- +
- + /* advance rotation for next frame */
- + angle += 70.0 * dt; /* 70 degrees per second */
- + if (angle > 3600.0)
- + angle -= 3600.0;
- +
- + draw( dpy, win );
- +
- + frames++;
- +
- + if (tRate0 < 0.0)
- + tRate0 = t;
- +
- + if (t - tRate0 >= 1.0) {
- + GLfloat seconds = t - tRate0;
- + GLfloat fps = frames / seconds;
- + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
- + fps);
- + tRate0 = t;
- +
- + /* Destroy window and create new one */
- + XDestroyWindow(dpy, win);
- + make_window(dpy, "glxgears",
- + (int)(fps * 100) % 100, (int)(fps * 100) % 100, /* x,y */
- + WinWidth, WinHeight, &win);
- + XMapWindow(dpy, win);
- +
- + frames = 0;
- + }
- + }
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + else
- + printf("Warrning: unknown parameter: %s\n", argv[i]);
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + fprintf(stderr, "Error: couldn't open display %s\n",
- + XDisplayName(dpyName));
- + return -1;
- + }
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + event_loop(dpy);
- +
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxdemo.c Mesa-7.8.1.patched/progs/xdemos/glxdemo.c
- --- Mesa-7.8.1/progs/xdemos/glxdemo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxdemo.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,127 @@
- +
- +
- +/*
- + * A demonstration of using the GLX functions. This program is in the
- + * public domain.
- + *
- + * Brian Paul
- + */
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +
- +
- +
- +static void redraw( Display *dpy, Window w )
- +{
- + printf("Redraw event\n");
- +
- + glClear( GL_COLOR_BUFFER_BIT );
- +
- + glColor3f( 1.0, 1.0, 0.0 );
- + glRectf( -0.8, -0.8, 0.8, 0.8 );
- +
- + glXSwapBuffers( dpy, w );
- +}
- +
- +
- +
- +static void resize( unsigned int width, unsigned int height )
- +{
- + printf("Resize event\n");
- + glViewport( 0, 0, width, height );
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
- +}
- +
- +
- +
- +static Window make_rgb_db_window( Display *dpy,
- + unsigned int width, unsigned int height )
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + glXMakeCurrent( dpy, win, ctx );
- +
- + return win;
- +}
- +
- +
- +static void event_loop( Display *dpy )
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent( dpy, &event );
- +
- + switch (event.type) {
- + case Expose:
- + redraw( dpy, event.xany.window );
- + break;
- + case ConfigureNotify:
- + resize( event.xconfigure.width, event.xconfigure.height );
- + break;
- + }
- + }
- +}
- +
- +
- +
- +int main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + Window win;
- +
- + dpy = XOpenDisplay(NULL);
- +
- + win = make_rgb_db_window( dpy, 300, 300 );
- +
- + glShadeModel( GL_FLAT );
- + glClearColor( 0.5, 0.5, 0.5, 1.0 );
- +
- + XMapWindow( dpy, win );
- +
- + event_loop( dpy );
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears.c Mesa-7.8.1.patched/progs/xdemos/glxgears.c
- --- Mesa-7.8.1/progs/xdemos/glxgears.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxgears.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,787 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/*
- + * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
- + * Port by Brian Paul 23 March 2001
- + *
- + * See usage() below for command line options.
- + */
- +
- +
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +
- +#ifndef GLX_MESA_swap_control
- +#define GLX_MESA_swap_control 1
- +typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
- +#endif
- +
- +
- +#define BENCHMARK
- +
- +#ifdef BENCHMARK
- +
- +/* XXX this probably isn't very portable */
- +
- +#include <sys/time.h>
- +#include <unistd.h>
- +
- +/* return current time (in seconds) */
- +static double
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
- +}
- +
- +#else /*BENCHMARK*/
- +
- +/* dummy */
- +static double
- +current_time(void)
- +{
- + /* update this function for other platforms! */
- + static double t = 0.0;
- + static int warn = 1;
- + if (warn) {
- + fprintf(stderr, "Warning: current_time() not implemented!!\n");
- + warn = 0;
- + }
- + return t += 1.0;
- +}
- +
- +#endif /*BENCHMARK*/
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +/** Event handler results: */
- +#define NOP 0
- +#define EXIT 1
- +#define DRAW 2
- +
- +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
- +static GLint gear1, gear2, gear3;
- +static GLfloat angle = 0.0;
- +
- +static GLboolean fullscreen = GL_FALSE; /* Create a single fullscreen window */
- +static GLboolean stereo = GL_FALSE; /* Enable stereo. */
- +static GLboolean animate = GL_TRUE; /* Animation */
- +static GLfloat eyesep = 5.0; /* Eye separation. */
- +static GLfloat fix_point = 40.0; /* Fixation point distance. */
- +static GLfloat left, right, asp; /* Stereo frustum params. */
- +
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +draw(void)
- +{
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + glPushMatrix();
- + glTranslatef(-3.0, -2.0, 0.0);
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(3.1, -2.0, 0.0);
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(-3.1, 4.2, 0.0);
- + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
- + glCallList(gear3);
- + glPopMatrix();
- +
- + glPopMatrix();
- +}
- +
- +
- +static void
- +draw_gears(void)
- +{
- + if (stereo) {
- + /* First left eye. */
- + glDrawBuffer(GL_BACK_LEFT);
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(left, right, -asp, asp, 5.0, 60.0);
- +
- + glMatrixMode(GL_MODELVIEW);
- +
- + glPushMatrix();
- + glTranslated(+0.5 * eyesep, 0.0, 0.0);
- + draw();
- + glPopMatrix();
- +
- + /* Then right eye. */
- + glDrawBuffer(GL_BACK_RIGHT);
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-right, -left, -asp, asp, 5.0, 60.0);
- +
- + glMatrixMode(GL_MODELVIEW);
- +
- + glPushMatrix();
- + glTranslated(-0.5 * eyesep, 0.0, 0.0);
- + draw();
- + glPopMatrix();
- + }
- + else {
- + draw();
- + }
- +}
- +
- +
- +/** Draw single frame, do SwapBuffers, compute FPS */
- +static void
- +draw_frame(Display *dpy, Window win)
- +{
- + static int frames = 0;
- + static double tRot0 = -1.0, tRate0 = -1.0;
- + double dt, t = current_time();
- +
- + if (tRot0 < 0.0)
- + tRot0 = t;
- + dt = t - tRot0;
- + tRot0 = t;
- +
- + if (animate) {
- + /* advance rotation for next frame */
- + angle += 70.0 * dt; /* 70 degrees per second */
- + if (angle > 3600.0)
- + angle -= 3600.0;
- + }
- +
- + draw_gears();
- + glXSwapBuffers(dpy, win);
- +
- + frames++;
- +
- + if (tRate0 < 0.0)
- + tRate0 = t;
- + if (t - tRate0 >= 5.0) {
- + GLfloat seconds = t - tRate0;
- + GLfloat fps = frames / seconds;
- + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
- + fps);
- + tRate0 = t;
- + frames = 0;
- + }
- +}
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(int width, int height)
- +{
- + glViewport(0, 0, (GLint) width, (GLint) height);
- +
- + if (stereo) {
- + GLfloat w;
- +
- + asp = (GLfloat) height / (GLfloat) width;
- + w = fix_point * (1.0 / 5.0);
- +
- + left = -5.0 * ((w - 0.5 * eyesep) / fix_point);
- + right = 5.0 * ((w + 0.5 * eyesep) / fix_point);
- + }
- + else {
- + GLfloat h = (GLfloat) height / (GLfloat) width;
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- + }
- +
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -40.0);
- +}
- +
- +
- +
- +static void
- +init(void)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
- + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_CULL_FACE);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + /* make the gears */
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(0.5, 2.0, 2.0, 10, 0.7);
- + glEndList();
- +
- + gear3 = glGenLists(1);
- + glNewList(gear3, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
- + gear(1.3, 2.0, 0.5, 10, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- +}
- +
- +
- +/**
- + * Remove window border/decorations.
- + */
- +static void
- +no_border( Display *dpy, Window w)
- +{
- + static const unsigned MWM_HINTS_DECORATIONS = (1 << 1);
- + static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5;
- +
- + typedef struct
- + {
- + unsigned long flags;
- + unsigned long functions;
- + unsigned long decorations;
- + long inputMode;
- + unsigned long status;
- + } PropMotifWmHints;
- +
- + PropMotifWmHints motif_hints;
- + Atom prop, proptype;
- + unsigned long flags = 0;
- +
- + /* setup the property */
- + motif_hints.flags = MWM_HINTS_DECORATIONS;
- + motif_hints.decorations = flags;
- +
- + /* get the atom for the property */
- + prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
- + if (!prop) {
- + /* something went wrong! */
- + return;
- + }
- +
- + /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
- + proptype = prop;
- +
- + XChangeProperty( dpy, w, /* display, window */
- + prop, proptype, /* property, type */
- + 32, /* format: 32-bit datums */
- + PropModeReplace, /* mode */
- + (unsigned char *) &motif_hints, /* data */
- + PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */
- + );
- +}
- +
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height,
- + Window *winRet, GLXContext *ctxRet)
- +{
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int stereoAttribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + GLX_STEREO,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + if (fullscreen) {
- + x = 0; y = 0;
- + width = DisplayWidth( dpy, scrnum );
- + height = DisplayHeight( dpy, scrnum );
- + }
- +
- + if (stereo)
- + visinfo = glXChooseVisual( dpy, scrnum, stereoAttribs );
- + else
- + visinfo = glXChooseVisual( dpy, scrnum, attribs );
- + if (!visinfo) {
- + if (stereo) {
- + printf("Error: couldn't get an RGB, "
- + "Double-buffered, Stereo visual\n");
- + } else
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + /* XXX this is a bad way to get a borderless window! */
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, x, y, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + if (fullscreen)
- + no_border(dpy, win);
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + XFree(visinfo);
- +
- + *winRet = win;
- + *ctxRet = ctx;
- +}
- +
- +
- +/**
- + * Determine whether or not a GLX extension is supported.
- + */
- +static int
- +is_glx_extension_supported(Display *dpy, const char *query)
- +{
- + const int scrnum = DefaultScreen(dpy);
- + const char *glx_extensions = NULL;
- + const size_t len = strlen(query);
- + const char *ptr;
- +
- + if (glx_extensions == NULL) {
- + glx_extensions = glXQueryExtensionsString(dpy, scrnum);
- + }
- +
- + ptr = strstr(glx_extensions, query);
- + return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
- +}
- +
- +
- +/**
- + * Attempt to determine whether or not the display is synched to vblank.
- + */
- +static void
- +query_vsync(Display *dpy, GLXDrawable drawable)
- +{
- + int interval = 0;
- +
- +#if defined(GLX_EXT_swap_control)
- + if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) {
- + unsigned int tmp = -1;
- + glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp);
- + interval = tmp;
- + } else
- +#endif
- + if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
- + PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA =
- + (PFNGLXGETSWAPINTERVALMESAPROC)
- + glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
- +
- + interval = (*pglXGetSwapIntervalMESA)();
- + } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) {
- + /* The default swap interval with this extension is 1. Assume that it
- + * is set to the default.
- + *
- + * Many Mesa-based drivers default to 0, but all of these drivers also
- + * export GLX_MESA_swap_control. In that case, this branch will never
- + * be taken, and the correct result should be reported.
- + */
- + interval = 1;
- + }
- +
- +
- + if (interval > 0) {
- + printf("Running synchronized to the vertical refresh. The framerate should be\n");
- + if (interval == 1) {
- + printf("approximately the same as the monitor refresh rate.\n");
- + } else if (interval > 1) {
- + printf("approximately 1/%d the monitor refresh rate.\n",
- + interval);
- + }
- + }
- +}
- +
- +/**
- + * Handle one X event.
- + * \return NOP, EXIT or DRAW
- + */
- +static int
- +handle_event(Display *dpy, Window win, XEvent *event)
- +{
- + (void) dpy;
- + (void) win;
- +
- + switch (event->type) {
- + case Expose:
- + return DRAW;
- + case ConfigureNotify:
- + reshape(event->xconfigure.width, event->xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event->xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event->xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return EXIT;
- + }
- + else if (buffer[0] == 'a' || buffer[0] == 'A') {
- + animate = !animate;
- + }
- + }
- + return DRAW;
- + }
- + }
- + return NOP;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, Window win)
- +{
- + while (1) {
- + int op;
- + while (!animate || XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + op = handle_event(dpy, win, &event);
- + if (op == EXIT)
- + return;
- + else if (op == DRAW)
- + break;
- + }
- +
- + draw_frame(dpy, win);
- + }
- +}
- +
- +
- +static void
- +usage(void)
- +{
- + printf("Usage:\n");
- + printf(" -display <displayname> set the display to run on\n");
- + printf(" -stereo run in stereo mode\n");
- + printf(" -fullscreen run in fullscreen mode\n");
- + printf(" -info display OpenGL renderer info\n");
- + printf(" -geometry WxH+X+Y window geometry\n");
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + unsigned int winWidth = 300, winHeight = 300;
- + int x = 0, y = 0;
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-stereo") == 0) {
- + stereo = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-fullscreen") == 0) {
- + fullscreen = GL_TRUE;
- + }
- + else if (i < argc-1 && strcmp(argv[i], "-geometry") == 0) {
- + XParseGeometry(argv[i+1], &x, &y, &winWidth, &winHeight);
- + i++;
- + }
- + else {
- + usage();
- + return -1;
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n",
- + dpyName ? dpyName : getenv("DISPLAY"));
- + return -1;
- + }
- +
- + make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, win, ctx);
- + query_vsync(dpy, win);
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + init();
- +
- + /* Set initial projection/viewing transformation.
- + * We can't be sure we'll get a ConfigureNotify event when the window
- + * first appears.
- + */
- + reshape(winWidth, winHeight);
- +
- + event_loop(dpy, win);
- +
- + glDeleteLists(gear1, 1);
- + glDeleteLists(gear2, 1);
- + glDeleteLists(gear3, 1);
- + glXMakeCurrent(dpy, None, NULL);
- + glXDestroyContext(dpy, ctx);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c
- --- Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,632 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/**
- + * \file glxgears_fbconfig.c
- + * Yet-another-version of gears. Originally ported to GLX by Brian Paul on
- + * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004.
- + *
- + * Command line options:
- + * -info print GL implementation information
- + *
- + * \author Brian Paul
- + * \author Ian Romanick <idr@us.ibm.com>
- + */
- +
- +
- +#define GLX_GLXEXT_PROTOTYPES
- +
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +#include <assert.h>
- +#include "pbutil.h"
- +
- +static PFNGLXCHOOSEFBCONFIGPROC choose_fbconfig = NULL;
- +static PFNGLXGETVISUALFROMFBCONFIGPROC get_visual_from_fbconfig = NULL;
- +static PFNGLXCREATENEWCONTEXTPROC create_new_context = NULL;
- +static PFNGLXCREATEWINDOWPROC create_window = NULL;
- +static PFNGLXDESTROYWINDOWPROC destroy_window = NULL;
- +
- +#define BENCHMARK
- +
- +#ifdef BENCHMARK
- +
- +/* XXX this probably isn't very portable */
- +
- +#include <sys/time.h>
- +#include <unistd.h>
- +
- +/* return current time (in seconds) */
- +static int
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (int) tv.tv_sec;
- +}
- +
- +#else /*BENCHMARK*/
- +
- +/* dummy */
- +static int
- +current_time(void)
- +{
- + return 0;
- +}
- +
- +#endif /*BENCHMARK*/
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
- +static GLint gear1, gear2, gear3;
- +static GLfloat angle = 0.0;
- +
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +draw(void)
- +{
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + glPushMatrix();
- + glTranslatef(-3.0, -2.0, 0.0);
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(3.1, -2.0, 0.0);
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(-3.1, 4.2, 0.0);
- + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
- + glCallList(gear3);
- + glPopMatrix();
- +
- + glPopMatrix();
- +}
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(int width, int height)
- +{
- + GLfloat h = (GLfloat) height / (GLfloat) width;
- +
- + glViewport(0, 0, (GLint) width, (GLint) height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -40.0);
- +}
- +
- +
- +static void
- +init(void)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
- + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_CULL_FACE);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + /* make the gears */
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(0.5, 2.0, 2.0, 10, 0.7);
- + glEndList();
- +
- + gear3 = glGenLists(1);
- + glNewList(gear3, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
- + gear(1.3, 2.0, 0.5, 10, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- +}
- +
- +
- +static GLXWindow
- +dummy_create_window(Display *dpy, GLXFBConfig config, Window win,
- + const int *attrib_list)
- +{
- + (void) dpy;
- + (void) config;
- + (void) attrib_list;
- +
- + return (GLXWindow) win;
- +}
- +
- +
- +static void
- +dummy_destroy_window(Display *dpy, GLXWindow win)
- +{
- + (void) dpy;
- + (void) win;
- +}
- +
- +
- +/**
- + * Initialize fbconfig related function pointers.
- + */
- +static void
- +init_fbconfig_functions(Display *dpy, int scrnum)
- +{
- + const char * glx_extensions;
- + const char * match;
- + static const char ext_name[] = "GLX_SGIX_fbconfig";
- + const size_t len = strlen( ext_name );
- + int major;
- + int minor;
- + GLboolean ext_version_supported;
- + GLboolean glx_1_3_supported;
- +
- +
- + /* Determine if GLX 1.3 or greater is supported.
- + */
- + glXQueryVersion(dpy, & major, & minor);
- + glx_1_3_supported = (major == 1) && (minor >= 3);
- +
- + /* Determine if GLX_SGIX_fbconfig is supported.
- + */
- + glx_extensions = glXQueryExtensionsString(dpy, scrnum);
- + match = strstr( glx_extensions, ext_name );
- +
- + ext_version_supported = (match != NULL)
- + && ((match[len] == '\0') || (match[len] == ' '));
- +
- + printf( "GLX 1.3 is %ssupported.\n",
- + (glx_1_3_supported) ? "" : "not " );
- + printf( "%s is %ssupported.\n",
- + ext_name, (ext_version_supported) ? "" : "not " );
- +
- + if ( glx_1_3_supported ) {
- + choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC)
- + glXGetProcAddressARB((GLubyte *) "glXChooseFBConfig");
- + get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
- + glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfig");
- + create_new_context = (PFNGLXCREATENEWCONTEXTPROC)
- + glXGetProcAddressARB((GLubyte *) "glXCreateNewContext");
- + create_window = (PFNGLXCREATEWINDOWPROC)
- + glXGetProcAddressARB((GLubyte *) "glXCreateWindow");
- + destroy_window = (PFNGLXDESTROYWINDOWPROC)
- + glXGetProcAddressARB((GLubyte *) "glXDestroyWindow");
- + }
- + else if ( ext_version_supported ) {
- + choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC)
- + glXGetProcAddressARB((GLubyte *) "glXChooseFBConfigSGIX");
- + get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
- + glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfigSGIX");
- + create_new_context = (PFNGLXCREATENEWCONTEXTPROC)
- + glXGetProcAddressARB((GLubyte *) "glXCreateContextWithConfigSGIX");
- + create_window = dummy_create_window;
- + destroy_window = dummy_destroy_window;
- + }
- + else {
- + printf( "This demo requires either GLX 1.3 or %s be supported.\n",
- + ext_name );
- + exit(1);
- + }
- +
- + if ( choose_fbconfig == NULL ) {
- + printf( "glXChooseFBConfig not found!\n" );
- + exit(1);
- + }
- +
- + if ( get_visual_from_fbconfig == NULL ) {
- + printf( "glXGetVisualFromFBConfig not found!\n" );
- + exit(1);
- + }
- +
- + if ( create_new_context == NULL ) {
- + printf( "glXCreateNewContext not found!\n" );
- + exit(1);
- + }
- +}
- +
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height,
- + Window *winRet, GLXWindow *glxWinRet, GLXContext *ctxRet)
- +{
- + int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER, GL_TRUE,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + GLXFBConfig * fbconfig;
- + int num_configs;
- + int scrnum;
- + int i;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXWindow glxWin;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + init_fbconfig_functions(dpy, scrnum);
- + fbconfig = (*choose_fbconfig)(dpy, scrnum, attrib, & num_configs);
- + if (fbconfig == NULL) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + printf("\nThe following fbconfigs meet the requirements. The first one "
- + "will be used.\n\n");
- + for ( i = 0 ; i < num_configs ; i++ ) {
- + PrintFBConfigInfo(dpy, scrnum, fbconfig[i], GL_TRUE);
- + }
- +
- + /* window attributes */
- + visinfo = (*get_visual_from_fbconfig)(dpy, fbconfig[0]);
- + assert(visinfo != NULL);
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + glxWin = (*create_window)(dpy, fbconfig[0], win, NULL);
- +
- + ctx = (*create_new_context)(dpy, fbconfig[0], GLX_RGBA_TYPE, NULL, GL_TRUE);
- + if (!ctx) {
- + printf("Error: glXCreateNewContext failed\n");
- + exit(1);
- + }
- +
- + XFree(fbconfig);
- +
- + *glxWinRet = glxWin;
- + *winRet = win;
- + *ctxRet = ctx;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, GLXWindow win)
- +{
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + /* we'll redraw below */
- + break;
- + case ConfigureNotify:
- + reshape(event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- + }
- + }
- + }
- + }
- + }
- +
- + /* next frame */
- + angle += 2.0;
- +
- + draw();
- + glXSwapBuffers(dpy, win);
- +
- + /* calc framerate */
- + {
- + static int t0 = -1;
- + static int frames = 0;
- + int t = current_time();
- +
- + if (t0 < 0)
- + t0 = t;
- +
- + frames++;
- +
- + if (t - t0 >= 5.0) {
- + GLfloat seconds = t - t0;
- + GLfloat fps = frames / seconds;
- + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
- + fps);
- + t0 = t;
- + frames = 0;
- + }
- + }
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + Window win;
- + GLXWindow glxWin;
- + GLXContext ctx;
- + const char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
- + return -1;
- + }
- +
- + make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &glxWin, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, glxWin, ctx);
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + init();
- +
- + event_loop(dpy, glxWin);
- +
- + glXDestroyContext(dpy, ctx);
- + destroy_window(dpy, glxWin);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c
- --- Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,547 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + * Copyright (C) 2008 Red Hat, Inc All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/**
- + * \file glxgears_pixmap.c
- + * Yet-another-version of gears. Originally ported to GLX by Brian Paul on
- + * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004.
- + *
- + * Command line options:
- + * -info print GL implementation information
- + *
- + * \author Brian Paul
- + * \author Ian Romanick <idr@us.ibm.com>
- + * \author Kristian Hoegsberg <krh@redhat.com>
- + */
- +
- +
- +#define GLX_GLXEXT_PROTOTYPES
- +
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +#include <assert.h>
- +#include "pbutil.h"
- +
- +#define BENCHMARK
- +
- +#ifdef BENCHMARK
- +
- +/* XXX this probably isn't very portable */
- +
- +#include <sys/time.h>
- +#include <unistd.h>
- +
- +/* return current time (in seconds) */
- +static int
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (int) tv.tv_sec;
- +}
- +
- +#else /*BENCHMARK*/
- +
- +/* dummy */
- +static int
- +current_time(void)
- +{
- + return 0;
- +}
- +
- +#endif /*BENCHMARK*/
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
- +static GLint gear1, gear2, gear3;
- +static GLfloat angle = 0.0;
- +
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +draw(void)
- +{
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + glPushMatrix();
- + glTranslatef(-3.0, -2.0, 0.0);
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(3.1, -2.0, 0.0);
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(-3.1, 4.2, 0.0);
- + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
- + glCallList(gear3);
- + glPopMatrix();
- +
- + glPopMatrix();
- +}
- +
- +
- +struct gears {
- + Window win;
- + GLXContext ctx;
- + Pixmap pixmap;
- + GLXPixmap glxpixmap;
- + GC gc;
- + int width, height;
- +};
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(struct gears *gears, int width, int height)
- +{
- + gears->width = width;
- + gears->height = height;
- +}
- +
- +
- +static void
- +init(int width, int height)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
- + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
- + GLfloat h = (GLfloat) height / (GLfloat) width;
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_CULL_FACE);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + /* make the gears */
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(0.5, 2.0, 2.0, 10, 0.7);
- + glEndList();
- +
- + gear3 = glGenLists(1);
- + glNewList(gear3, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
- + gear(1.3, 2.0, 0.5, 10, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- +
- + glViewport(0, 0, (GLint) width, (GLint) height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -40.0);
- +}
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height, struct gears *gears)
- +{
- + int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER, GL_FALSE,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + GLXFBConfig * fbconfig;
- + int num_configs;
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + XVisualInfo *visinfo;
- +
- + gears->width = width;
- + gears->height = height;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + fbconfig = glXChooseFBConfig(dpy, scrnum, attrib, & num_configs);
- + if (fbconfig == NULL) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
- + assert(visinfo != NULL);
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + gears->win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, gears->win, &sizehints);
- + XSetStandardProperties(dpy, gears->win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + gears->gc = XCreateGC(dpy, gears->win, 0, NULL);
- +
- + gears->pixmap = XCreatePixmap(dpy, gears->win,
- + width, height, visinfo->depth);
- + if (!gears->pixmap) {
- + printf("Error: XCreatePixmap failed\n");
- + exit(-1);
- + }
- +
- + gears->glxpixmap = glXCreatePixmap(dpy, fbconfig[0], gears->pixmap, NULL);
- + if (!gears->glxpixmap) {
- + printf("Error: glXCreatePixmap failed\n");
- + exit(-1);
- + }
- +
- + gears->ctx = glXCreateNewContext(dpy, fbconfig[0],
- + GLX_RGBA_TYPE, NULL, GL_TRUE);
- + if (!gears->ctx) {
- + printf("Error: glXCreateNewContext failed\n");
- + exit(1);
- + }
- +
- + XFree(fbconfig);
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, struct gears *gears)
- +{
- + int x, y;
- +
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + /* we'll redraw below */
- + break;
- + case ConfigureNotify:
- + reshape(gears, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- + }
- + }
- + }
- + }
- + }
- +
- + /* next frame */
- + angle += 2.0;
- +
- + draw();
- + glFinish();
- +
- + for (x = 0; x < gears->width; x += 100)
- + for (y = 0; y < gears->width; y += 100)
- + XCopyArea(dpy, gears->pixmap, gears->win, gears->gc,
- + 50, 50, 100, 100, x, y);
- +
- + /* calc framerate */
- + {
- + static int t0 = -1;
- + static int frames = 0;
- + int t = current_time();
- +
- + if (t0 < 0)
- + t0 = t;
- +
- + frames++;
- +
- + if (t - t0 >= 5.0) {
- + GLfloat seconds = t - t0;
- + GLfloat fps = frames / seconds;
- + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
- + fps);
- + t0 = t;
- + frames = 0;
- + }
- + }
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + const char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + struct gears gears;
- + int i, width = 200, height = 200;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
- + return -1;
- + }
- +
- + make_window(dpy, "glxgears", 0, 0, width, height, &gears);
- + XMapWindow(dpy, gears.win);
- + glXMakeCurrent(dpy, gears.glxpixmap, gears.ctx);
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + init(width, height);
- +
- + event_loop(dpy, &gears);
- +
- + glXDestroyContext(dpy, gears.ctx);
- + XDestroyWindow(dpy, gears.win);
- + glXDestroyPixmap(dpy, gears.pixmap);
- + XFreePixmap(dpy, gears.pixmap);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxheads.c Mesa-7.8.1.patched/progs/xdemos/glxheads.c
- --- Mesa-7.8.1/progs/xdemos/glxheads.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxheads.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,313 @@
- +
- +/*
- + * Exercise multiple GLX connections on multiple X displays.
- + * Direct GLX contexts are attempted first, then indirect.
- + * Each window will display a spinning green triangle.
- + *
- + * Copyright (C) 2000 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +
- +
- +
- +/*
- + * Each display/window/context:
- + */
- +struct head {
- + char DisplayName[1000];
- + Display *Dpy;
- + Window Win;
- + GLXContext Context;
- + float Angle;
- + char Renderer[1000];
- + char Vendor[1000];
- + char Version[1000];
- +};
- +
- +
- +#define MAX_HEADS 20
- +static struct head Heads[MAX_HEADS];
- +static int NumHeads = 0;
- +
- +
- +static void
- +Error(const char *display, const char *msg)
- +{
- + fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg);
- + exit(1);
- +}
- +
- +
- +static struct head *
- +AddHead(const char *displayName)
- +{
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + XVisualInfo *visinfo;
- + int width = 300, height = 300;
- + int xpos = 10, ypos = 10;
- +
- + if (NumHeads >= MAX_HEADS)
- + return NULL;
- +
- + dpy = XOpenDisplay(displayName);
- + if (!dpy) {
- + Error(displayName, "Unable to open display");
- + return NULL;
- + }
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + visinfo = glXChooseVisual(dpy, scrnum, attrib);
- + if (!visinfo) {
- + Error(displayName, "Unable to find RGB, double-buffered visual");
- + return NULL;
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (!win) {
- + Error(displayName, "Couldn't create window");
- + return NULL;
- + }
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, displayName, displayName,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + ctx = glXCreateContext(dpy, visinfo, NULL, True);
- + if (!ctx) {
- + Error(displayName, "Couldn't create GLX context");
- + return NULL;
- + }
- +
- + XMapWindow(dpy, win);
- +
- + if (!glXMakeCurrent(dpy, win, ctx)) {
- + Error(displayName, "glXMakeCurrent failed");
- + printf("glXMakeCurrent failed in Redraw()\n");
- + return NULL;
- + }
- +
- + /* save the info for this head */
- + {
- + struct head *h = &Heads[NumHeads];
- + const char * tmp;
- +
- + if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
- + Error(displayName, "displayName string length overflow");
- + return NULL;
- + }
- + strcpy(h->DisplayName, displayName);
- +
- + h->Dpy = dpy;
- + h->Win = win;
- + h->Context = ctx;
- + h->Angle = 0.0;
- +
- + tmp = (char *) glGetString(GL_VERSION);
- + if (strlen(tmp) + 1 > sizeof(h->Version)) {
- + Error(displayName, "GL_VERSION string length overflow");
- + return NULL;
- + }
- + strcpy(h->Version, tmp);
- +
- + tmp = (char *) glGetString(GL_VENDOR);
- + if (strlen(tmp) + 1 > sizeof(h->Vendor)) {
- + Error(displayName, "GL_VENDOR string length overflow");
- + return NULL;
- + }
- + strcpy(h->Vendor, tmp);
- +
- + tmp = (char *) glGetString(GL_RENDERER);
- + if (strlen(tmp) + 1 > sizeof(h->Renderer)) {
- + Error(displayName, "GL_RENDERER string length overflow");
- + return NULL;
- + }
- + strcpy(h->Renderer, tmp);
- +
- + NumHeads++;
- + return &Heads[NumHeads-1];
- + }
- +
- +}
- +
- +
- +static void
- +Redraw(struct head *h)
- +{
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed");
- + printf("glXMakeCurrent failed in Redraw()\n");
- + return;
- + }
- +
- + h->Angle += 1.0;
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.5, 0.5, 0.5, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + /* draw green triangle */
- + glColor3f(0.0, 1.0, 0.0);
- + glPushMatrix();
- + glRotatef(h->Angle, 0, 0, 1);
- + glBegin(GL_TRIANGLES);
- + glVertex2f(0, 0.8);
- + glVertex2f(-0.8, -0.7);
- + glVertex2f(0.8, -0.7);
- + glEnd();
- + glPopMatrix();
- +
- + glXSwapBuffers(h->Dpy, h->Win);
- +}
- +
- +
- +
- +static void
- +Resize(const struct head *h, unsigned int width, unsigned int height)
- +{
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
- + return;
- + }
- + glFlush();
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- +}
- +
- +
- +
- +static void
- +EventLoop(void)
- +{
- + while (1) {
- + int i;
- + for (i = 0; i < NumHeads; i++) {
- + struct head *h = &Heads[i];
- + while (XPending(h->Dpy) > 0) {
- + XEvent event;
- + XNextEvent(h->Dpy, &event);
- + if (event.xany.window == h->Win) {
- + switch (event.type) {
- + case Expose:
- + Redraw(h);
- + break;
- + case ConfigureNotify:
- + Resize(h, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + return;
- + default:
- + /*no-op*/ ;
- + }
- + }
- + else {
- + printf("window mismatch\n");
- + }
- + }
- + Redraw(h);
- + }
- + usleep(1);
- + }
- +}
- +
- +
- +
- +static void
- +PrintInfo(const struct head *h)
- +{
- + printf("Name: %s\n", h->DisplayName);
- + printf(" Display: %p\n", (void *) h->Dpy);
- + printf(" Window: 0x%x\n", (int) h->Win);
- + printf(" Context: 0x%lx\n", (long) h->Context);
- + printf(" GL_VERSION: %s\n", h->Version);
- + printf(" GL_VENDOR: %s\n", h->Vendor);
- + printf(" GL_RENDERER: %s\n", h->Renderer);
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + int i;
- + if (argc == 1) {
- + struct head *h;
- + printf("glxheads: exercise multiple GLX connections (any key = exit)\n");
- + printf("Usage:\n");
- + printf(" glxheads xdisplayname ...\n");
- + printf("Example:\n");
- + printf(" glxheads :0 mars:0 venus:1\n");
- +
- + h = AddHead(XDisplayName(NULL));
- + if (h)
- + PrintInfo(h);
- + }
- + else {
- + for (i = 1; i < argc; i++) {
- + const char *name = argv[i];
- + struct head *h = AddHead(name);
- + if (h) {
- + PrintInfo(h);
- + }
- + }
- + }
- +
- + EventLoop();
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxinfo.c Mesa-7.8.1.patched/progs/xdemos/glxinfo.c
- --- Mesa-7.8.1/progs/xdemos/glxinfo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxinfo.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,1195 @@
- +/*
- + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * This program is a work-alike of the IRIX glxinfo program.
- + * Command line options:
- + * -t print wide table
- + * -v print verbose information
- + * -display DisplayName specify the X display to interogate
- + * -b only print ID of "best" visual on screen 0
- + * -i use indirect rendering connection only
- + * -l print interesting OpenGL limits (added 5 Sep 2002)
- + *
- + * Brian Paul 26 January 2000
- + */
- +
- +#define GLX_GLXEXT_PROTOTYPES
- +
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <stdlib.h>
- +
- +
- +#ifndef GLX_NONE_EXT
- +#define GLX_NONE_EXT 0x8000
- +#endif
- +
- +#ifndef GLX_TRANSPARENT_RGB
- +#define GLX_TRANSPARENT_RGB 0x8008
- +#endif
- +
- +#ifndef GLX_RGBA_BIT
- +#define GLX_RGBA_BIT 0x00000001
- +#endif
- +
- +#ifndef GLX_COLOR_INDEX_BIT
- +#define GLX_COLOR_INDEX_BIT 0x00000002
- +#endif
- +
- +typedef enum
- +{
- + Normal,
- + Wide,
- + Verbose
- +} InfoMode;
- +
- +
- +struct visual_attribs
- +{
- + /* X visual attribs */
- + int id;
- + int klass;
- + int depth;
- + int redMask, greenMask, blueMask;
- + int colormapSize;
- + int bitsPerRGB;
- +
- + /* GL visual attribs */
- + int supportsGL;
- + int transparentType;
- + int transparentRedValue;
- + int transparentGreenValue;
- + int transparentBlueValue;
- + int transparentAlphaValue;
- + int transparentIndexValue;
- + int bufferSize;
- + int level;
- + int render_type;
- + int doubleBuffer;
- + int stereo;
- + int auxBuffers;
- + int redSize, greenSize, blueSize, alphaSize;
- + int depthSize;
- + int stencilSize;
- + int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
- + int numSamples, numMultisample;
- + int visualCaveat;
- +};
- +
- +
- +/*
- + * Print a list of extensions, with word-wrapping.
- + */
- +static void
- +print_extension_list(const char *ext)
- +{
- + const char *indentString = " ";
- + const int indent = 4;
- + const int max = 79;
- + int width, i, j;
- +
- + if (!ext || !ext[0])
- + return;
- +
- + width = indent;
- + printf("%s", indentString);
- + i = j = 0;
- + while (1) {
- + if (ext[j] == ' ' || ext[j] == 0) {
- + /* found end of an extension name */
- + const int len = j - i;
- + if (width + len > max) {
- + /* start a new line */
- + printf("\n");
- + width = indent;
- + printf("%s", indentString);
- + }
- + /* print the extension name between ext[i] and ext[j] */
- + while (i < j) {
- + printf("%c", ext[i]);
- + i++;
- + }
- + /* either we're all done, or we'll continue with next extension */
- + width += len + 1;
- + if (ext[j] == 0) {
- + break;
- + }
- + else {
- + i++;
- + j++;
- + if (ext[j] == 0)
- + break;
- + printf(", ");
- + width += 2;
- + }
- + }
- + j++;
- + }
- + printf("\n");
- +}
- +
- +
- +static void
- +print_display_info(Display *dpy)
- +{
- + printf("name of display: %s\n", DisplayString(dpy));
- +}
- +
- +
- +/**
- + * Print interesting limits for vertex/fragment programs.
- + */
- +static void
- +print_program_limits(GLenum target)
- +{
- +#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
- + struct token_name {
- + GLenum token;
- + const char *name;
- + };
- + static const struct token_name common_limits[] = {
- + { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB" },
- + { GL_MAX_PROGRAM_PARAMETERS_ARB, "GL_MAX_PROGRAM_PARAMETERS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB" },
- + { GL_MAX_PROGRAM_ATTRIBS_ARB, "GL_MAX_PROGRAM_ATTRIBS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB" },
- + { GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" },
- + { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" },
- + { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" },
- + { (GLenum) 0, NULL }
- + };
- + static const struct token_name fragment_limits[] = {
- + { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB" },
- + { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" },
- + { (GLenum) 0, NULL }
- + };
- +
- + PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC)
- + glXGetProcAddressARB((GLubyte *) "glGetProgramivARB");
- +
- + GLint max[1];
- + int i;
- +
- + if (target == GL_VERTEX_PROGRAM_ARB) {
- + printf(" GL_VERTEX_PROGRAM_ARB:\n");
- + }
- + else if (target == GL_FRAGMENT_PROGRAM_ARB) {
- + printf(" GL_FRAGMENT_PROGRAM_ARB:\n");
- + }
- + else {
- + return; /* something's wrong */
- + }
- +
- + for (i = 0; common_limits[i].token; i++) {
- + GetProgramivARB_func(target, common_limits[i].token, max);
- + if (glGetError() == GL_NO_ERROR) {
- + printf(" %s = %d\n", common_limits[i].name, max[0]);
- + }
- + }
- + if (target == GL_FRAGMENT_PROGRAM_ARB) {
- + for (i = 0; fragment_limits[i].token; i++) {
- + GetProgramivARB_func(target, fragment_limits[i].token, max);
- + if (glGetError() == GL_NO_ERROR) {
- + printf(" %s = %d\n", fragment_limits[i].name, max[0]);
- + }
- + }
- + }
- +#endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */
- +}
- +
- +
- +/**
- + * Print interesting limits for vertex/fragment shaders.
- + */
- +static void
- +print_shader_limits(GLenum target)
- +{
- + struct token_name {
- + GLenum token;
- + const char *name;
- + };
- +#if defined(GL_ARB_vertex_shader)
- + static const struct token_name vertex_limits[] = {
- + { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB" },
- + { GL_MAX_VARYING_FLOATS_ARB, "GL_MAX_VARYING_FLOATS_ARB" },
- + { GL_MAX_VERTEX_ATTRIBS_ARB, "GL_MAX_VERTEX_ATTRIBS_ARB" },
- + { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
- + { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB" },
- + { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB" },
- + { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
- + { (GLenum) 0, NULL }
- + };
- +#endif
- +#if defined(GL_ARB_fragment_shader)
- + static const struct token_name fragment_limits[] = {
- + { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB" },
- + { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
- + { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
- + { (GLenum) 0, NULL }
- + };
- +#endif
- + GLint max[1];
- + int i;
- +
- +#if defined(GL_ARB_vertex_shader)
- + if (target == GL_VERTEX_SHADER_ARB) {
- + printf(" GL_VERTEX_SHADER_ARB:\n");
- + for (i = 0; vertex_limits[i].token; i++) {
- + glGetIntegerv(vertex_limits[i].token, max);
- + if (glGetError() == GL_NO_ERROR) {
- + printf(" %s = %d\n", vertex_limits[i].name, max[0]);
- + }
- + }
- + }
- +#endif
- +#if defined(GL_ARB_fragment_shader)
- + if (target == GL_FRAGMENT_SHADER_ARB) {
- + printf(" GL_FRAGMENT_SHADER_ARB:\n");
- + for (i = 0; fragment_limits[i].token; i++) {
- + glGetIntegerv(fragment_limits[i].token, max);
- + if (glGetError() == GL_NO_ERROR) {
- + printf(" %s = %d\n", fragment_limits[i].name, max[0]);
- + }
- + }
- + }
- +#endif
- +}
- +
- +
- +/**
- + * Print interesting OpenGL implementation limits.
- + */
- +static void
- +print_limits(const char *extensions)
- +{
- + struct token_name {
- + GLuint count;
- + GLenum token;
- + const char *name;
- + };
- + static const struct token_name limits[] = {
- + { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" },
- + { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" },
- + { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" },
- + { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" },
- + { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" },
- + { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" },
- + { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" },
- + { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" },
- + { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" },
- + { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" },
- + { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" },
- + { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" },
- + { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" },
- + { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" },
- + { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" },
- + { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" },
- + { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" },
- + { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" },
- + { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" },
- + { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" },
- + { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" },
- +#if defined(GL_ARB_texture_cube_map)
- + { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" },
- +#endif
- +#if defined(GLX_NV_texture_rectangle)
- + { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" },
- +#endif
- +#if defined(GL_ARB_texture_compression)
- + { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" },
- +#endif
- +#if defined(GL_ARB_multitexture)
- + { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" },
- +#endif
- +#if defined(GL_EXT_texture_lod_bias)
- + { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" },
- +#endif
- +#if defined(GL_EXT_texture_filter_anisotropic)
- + { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" },
- +#endif
- +#if defined(GL_ARB_draw_buffers)
- + { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB" },
- +#endif
- + { 0, (GLenum) 0, NULL }
- + };
- + GLint i, max[2];
- +
- + printf("OpenGL limits:\n");
- + for (i = 0; limits[i].count; i++) {
- + glGetIntegerv(limits[i].token, max);
- + if (glGetError() == GL_NO_ERROR) {
- + if (limits[i].count == 1)
- + printf(" %s = %d\n", limits[i].name, max[0]);
- + else /* XXX fix if we ever query something with more than 2 values */
- + printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]);
- + }
- + }
- +
- + /* these don't fit into the above mechanism, unfortunately */
- + glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max);
- + glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1);
- + if (glGetError() == GL_NONE) {
- + printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]);
- + }
- +
- +#if defined(GL_ARB_vertex_program)
- + if (strstr(extensions, "GL_ARB_vertex_program")) {
- + print_program_limits(GL_VERTEX_PROGRAM_ARB);
- + }
- +#endif
- +#if defined(GL_ARB_fragment_program)
- + if (strstr(extensions, "GL_ARB_fragment_program")) {
- + print_program_limits(GL_FRAGMENT_PROGRAM_ARB);
- + }
- +#endif
- +#if defined(GL_ARB_vertex_shader)
- + if (strstr(extensions, "GL_ARB_vertex_shader")) {
- + print_shader_limits(GL_VERTEX_SHADER_ARB);
- + }
- +#endif
- +#if defined(GL_ARB_fragment_shader)
- + if (strstr(extensions, "GL_ARB_fragment_shader")) {
- + print_shader_limits(GL_FRAGMENT_SHADER_ARB);
- + }
- +#endif
- +}
- +
- +
- +static void
- +print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
- +{
- + Window win;
- + int attribSingle[] = {
- + GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + None };
- + int attribDouble[] = {
- + GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- +
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + GLXContext ctx = NULL;
- + XVisualInfo *visinfo;
- + int width = 100, height = 100;
- +
- + root = RootWindow(dpy, scrnum);
- +
- + /*
- + * Find a basic GLX visual. We'll then create a rendering context and
- + * query various info strings.
- + */
- + visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
- + if (!visinfo)
- + visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
- +
- + if (visinfo)
- + ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
- +
- +#ifdef GLX_VERSION_1_3
- + /* Try glXChooseFBConfig() if glXChooseVisual didn't work.
- + * XXX when would that happen?
- + */
- + if (!visinfo) {
- + int fbAttribSingle[] = {
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER, GL_FALSE,
- + None };
- + int fbAttribDouble[] = {
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER, GL_TRUE,
- + None };
- + GLXFBConfig *configs = NULL;
- + int nConfigs;
- +
- + configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
- + if (!configs)
- + configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
- +
- + if (configs) {
- + visinfo = glXGetVisualFromFBConfig(dpy, configs[0]);
- + ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect);
- + XFree(configs);
- + }
- + }
- +#endif
- +
- + if (!visinfo) {
- + fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
- + return;
- + }
- +
- + if (!ctx) {
- + fprintf(stderr, "Error: glXCreateContext failed\n");
- + XFree(visinfo);
- + return;
- + }
- +
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- + win = XCreateWindow(dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- +
- + if (glXMakeCurrent(dpy, win, ctx)) {
- + const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
- + const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
- + const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
- + const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
- + const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
- + const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
- + const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
- + const char *glVendor = (const char *) glGetString(GL_VENDOR);
- + const char *glRenderer = (const char *) glGetString(GL_RENDERER);
- + const char *glVersion = (const char *) glGetString(GL_VERSION);
- + const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
- + int glxVersionMajor;
- + int glxVersionMinor;
- + char *displayName = NULL;
- + char *colon = NULL, *period = NULL;
- +
- + if (! glXQueryVersion( dpy, & glxVersionMajor, & glxVersionMinor )) {
- + fprintf(stderr, "Error: glXQueryVersion failed\n");
- + exit(1);
- + }
- +
- + /* Strip the screen number from the display name, if present. */
- + if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
- + fprintf(stderr, "Error: malloc() failed\n");
- + exit(1);
- + }
- + strcpy(displayName, DisplayString(dpy));
- + colon = strrchr(displayName, ':');
- + if (colon) {
- + period = strchr(colon, '.');
- + if (period)
- + *period = '\0';
- + }
- + printf("display: %s screen: %d\n", displayName, scrnum);
- + free(displayName);
- + printf("direct rendering: ");
- + if (glXIsDirect(dpy, ctx)) {
- + printf("Yes\n");
- + } else {
- + if (!allowDirect) {
- + printf("No (-i specified)\n");
- + } else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
- + printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
- + } else {
- + printf("No (If you want to find out why, try setting "
- + "LIBGL_DEBUG=verbose)\n");
- + }
- + }
- + printf("server glx vendor string: %s\n", serverVendor);
- + printf("server glx version string: %s\n", serverVersion);
- + printf("server glx extensions:\n");
- + print_extension_list(serverExtensions);
- + printf("client glx vendor string: %s\n", clientVendor);
- + printf("client glx version string: %s\n", clientVersion);
- + printf("client glx extensions:\n");
- + print_extension_list(clientExtensions);
- + printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor);
- + printf("GLX extensions:\n");
- + print_extension_list(glxExtensions);
- + printf("OpenGL vendor string: %s\n", glVendor);
- + printf("OpenGL renderer string: %s\n", glRenderer);
- + printf("OpenGL version string: %s\n", glVersion);
- +#ifdef GL_VERSION_2_0
- + if (glVersion[0] >= '2' && glVersion[1] == '.') {
- + char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
- + printf("OpenGL shading language version string: %s\n", v);
- + }
- +#endif
- +
- + printf("OpenGL extensions:\n");
- + print_extension_list(glExtensions);
- + if (limits)
- + print_limits(glExtensions);
- + }
- + else {
- + fprintf(stderr, "Error: glXMakeCurrent failed\n");
- + }
- +
- + glXDestroyContext(dpy, ctx);
- + XFree(visinfo);
- + XDestroyWindow(dpy, win);
- +}
- +
- +
- +static const char *
- +visual_class_name(int cls)
- +{
- + switch (cls) {
- + case StaticColor:
- + return "StaticColor";
- + case PseudoColor:
- + return "PseudoColor";
- + case StaticGray:
- + return "StaticGray";
- + case GrayScale:
- + return "GrayScale";
- + case TrueColor:
- + return "TrueColor";
- + case DirectColor:
- + return "DirectColor";
- + default:
- + return "";
- + }
- +}
- +
- +
- +static const char *
- +visual_class_abbrev(int cls)
- +{
- + switch (cls) {
- + case StaticColor:
- + return "sc";
- + case PseudoColor:
- + return "pc";
- + case StaticGray:
- + return "sg";
- + case GrayScale:
- + return "gs";
- + case TrueColor:
- + return "tc";
- + case DirectColor:
- + return "dc";
- + default:
- + return "";
- + }
- +}
- +
- +static const char *
- +visual_render_type_name(int type)
- +{
- + switch (type) {
- + case GLX_RGBA_BIT:
- + return "rgba";
- + case GLX_COLOR_INDEX_BIT:
- + return "ci";
- + case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
- + return "rgba|ci";
- + default:
- + return "";
- + }
- +}
- +
- +static GLboolean
- +get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
- + struct visual_attribs *attribs)
- +{
- + const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
- + int rgba;
- +
- + memset(attribs, 0, sizeof(struct visual_attribs));
- +
- + attribs->id = vInfo->visualid;
- +#if defined(__cplusplus) || defined(c_plusplus)
- + attribs->klass = vInfo->c_class;
- +#else
- + attribs->klass = vInfo->class;
- +#endif
- + attribs->depth = vInfo->depth;
- + attribs->redMask = vInfo->red_mask;
- + attribs->greenMask = vInfo->green_mask;
- + attribs->blueMask = vInfo->blue_mask;
- + attribs->colormapSize = vInfo->colormap_size;
- + attribs->bitsPerRGB = vInfo->bits_per_rgb;
- +
- + if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
- + !attribs->supportsGL)
- + return GL_FALSE;
- + glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
- + glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
- + glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
- + if (rgba)
- + attribs->render_type = GLX_RGBA_BIT;
- + else
- + attribs->render_type = GLX_COLOR_INDEX_BIT;
- +
- + glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
- + glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
- + glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
- + glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
- + glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
- + glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
- + glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
- + glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
- + glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
- + glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
- + glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
- + glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
- + glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
- +
- + /* get transparent pixel stuff */
- + glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
- + if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
- + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
- + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
- + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
- + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
- + }
- + else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
- + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
- + }
- +
- + /* multisample attribs */
- +#ifdef GLX_ARB_multisample
- + if (ext && strstr(ext, "GLX_ARB_multisample")) {
- + glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
- + glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
- + }
- +#endif
- + else {
- + attribs->numSamples = 0;
- + attribs->numMultisample = 0;
- + }
- +
- +#if defined(GLX_EXT_visual_rating)
- + if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
- + glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
- + }
- + else {
- + attribs->visualCaveat = GLX_NONE_EXT;
- + }
- +#else
- + attribs->visualCaveat = 0;
- +#endif
- +
- + return GL_TRUE;
- +}
- +
- +#ifdef GLX_VERSION_1_3
- +
- +static int
- +glx_token_to_visual_class(int visual_type)
- +{
- + switch (visual_type) {
- + case GLX_TRUE_COLOR:
- + return TrueColor;
- + case GLX_DIRECT_COLOR:
- + return DirectColor;
- + case GLX_PSEUDO_COLOR:
- + return PseudoColor;
- + case GLX_STATIC_COLOR:
- + return StaticColor;
- + case GLX_GRAY_SCALE:
- + return GrayScale;
- + case GLX_STATIC_GRAY:
- + return StaticGray;
- + case GLX_NONE:
- + default:
- + return None;
- + }
- +}
- +
- +static GLboolean
- +get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
- + struct visual_attribs *attribs)
- +{
- + int visual_type;
- +
- + memset(attribs, 0, sizeof(struct visual_attribs));
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id);
- +
- +#if 0
- + attribs->depth = vInfo->depth;
- + attribs->redMask = vInfo->red_mask;
- + attribs->greenMask = vInfo->green_mask;
- + attribs->blueMask = vInfo->blue_mask;
- + attribs->colormapSize = vInfo->colormap_size;
- + attribs->bitsPerRGB = vInfo->bits_per_rgb;
- +#endif
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
- + attribs->klass = glx_token_to_visual_class(visual_type);
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
- +
- + /* get transparent pixel stuff */
- + glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
- + if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
- + }
- + else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
- + }
- +
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
- + glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
- +
- + return GL_TRUE;
- +}
- +
- +#endif
- +
- +
- +
- +static void
- +print_visual_attribs_verbose(const struct visual_attribs *attribs)
- +{
- + printf("Visual ID: %x depth=%d class=%s\n",
- + attribs->id, attribs->depth, visual_class_name(attribs->klass));
- + printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
- + attribs->bufferSize, attribs->level,
- + visual_render_type_name(attribs->render_type),
- + attribs->doubleBuffer, attribs->stereo);
- + printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
- + attribs->redSize, attribs->greenSize,
- + attribs->blueSize, attribs->alphaSize);
- + printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
- + attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
- + printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
- + attribs->accumRedSize, attribs->accumGreenSize,
- + attribs->accumBlueSize, attribs->accumAlphaSize);
- + printf(" multiSample=%d multiSampleBuffers=%d\n",
- + attribs->numSamples, attribs->numMultisample);
- +#ifdef GLX_EXT_visual_rating
- + if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
- + printf(" visualCaveat=None\n");
- + else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
- + printf(" visualCaveat=Slow\n");
- + else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
- + printf(" visualCaveat=Nonconformant\n");
- +#endif
- + if (attribs->transparentType == GLX_NONE) {
- + printf(" Opaque.\n");
- + }
- + else if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
- + printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue);
- + }
- + else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
- + printf(" Transparent index=%d\n",attribs->transparentIndexValue);
- + }
- +}
- +
- +
- +static void
- +print_visual_attribs_short_header(void)
- +{
- + printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
- + printf(" id dep cl sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n");
- + printf("----------------------------------------------------------------------\n");
- +}
- +
- +
- +static void
- +print_visual_attribs_short(const struct visual_attribs *attribs)
- +{
- + char *caveat = NULL;
- +#ifdef GLX_EXT_visual_rating
- + if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
- + caveat = "None";
- + else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
- + caveat = "Slow";
- + else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
- + caveat = "Ncon";
- + else
- + caveat = "None";
- +#else
- + caveat = "None";
- +#endif
- +
- + printf("0x%02x %2d %2s %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d",
- + attribs->id,
- + attribs->depth,
- + visual_class_abbrev(attribs->klass),
- + attribs->transparentType != GLX_NONE,
- + attribs->bufferSize,
- + attribs->level,
- + (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ',
- + (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ',
- + attribs->doubleBuffer ? 'y' : '.',
- + attribs->stereo ? 'y' : '.',
- + attribs->redSize, attribs->greenSize,
- + attribs->blueSize, attribs->alphaSize,
- + attribs->auxBuffers,
- + attribs->depthSize,
- + attribs->stencilSize
- + );
- +
- + printf(" %2d %2d %2d %2d %2d %1d %s\n",
- + attribs->accumRedSize, attribs->accumGreenSize,
- + attribs->accumBlueSize, attribs->accumAlphaSize,
- + attribs->numSamples, attribs->numMultisample,
- + caveat
- + );
- +}
- +
- +
- +static void
- +print_visual_attribs_long_header(void)
- +{
- + printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
- + printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
- + printf("----------------------------------------------------------------------------------------------------\n");
- +}
- +
- +
- +static void
- +print_visual_attribs_long(const struct visual_attribs *attribs)
- +{
- + printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
- + attribs->id,
- + attribs->depth,
- + visual_class_name(attribs->klass),
- + attribs->transparentType != GLX_NONE,
- + attribs->bufferSize,
- + attribs->level,
- + visual_render_type_name(attribs->render_type),
- + attribs->doubleBuffer,
- + attribs->stereo,
- + attribs->redSize, attribs->greenSize,
- + attribs->blueSize, attribs->alphaSize
- + );
- +
- + printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
- + attribs->auxBuffers,
- + attribs->depthSize,
- + attribs->stencilSize,
- + attribs->accumRedSize, attribs->accumGreenSize,
- + attribs->accumBlueSize, attribs->accumAlphaSize,
- + attribs->numSamples, attribs->numMultisample
- + );
- +}
- +
- +
- +static void
- +print_visual_info(Display *dpy, int scrnum, InfoMode mode)
- +{
- + XVisualInfo theTemplate;
- + XVisualInfo *visuals;
- + int numVisuals, numGlxVisuals;
- + long mask;
- + int i;
- + struct visual_attribs attribs;
- +
- + /* get list of all visuals on this screen */
- + theTemplate.screen = scrnum;
- + mask = VisualScreenMask;
- + visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
- +
- + numGlxVisuals = 0;
- + for (i = 0; i < numVisuals; i++) {
- + if (get_visual_attribs(dpy, &visuals[i], &attribs))
- + numGlxVisuals++;
- + }
- +
- + if (numGlxVisuals == 0)
- + return;
- +
- + printf("%d GLX Visuals\n", numGlxVisuals);
- +
- + if (mode == Normal)
- + print_visual_attribs_short_header();
- + else if (mode == Wide)
- + print_visual_attribs_long_header();
- +
- + for (i = 0; i < numVisuals; i++) {
- + if (!get_visual_attribs(dpy, &visuals[i], &attribs))
- + continue;
- +
- + if (mode == Verbose)
- + print_visual_attribs_verbose(&attribs);
- + else if (mode == Normal)
- + print_visual_attribs_short(&attribs);
- + else if (mode == Wide)
- + print_visual_attribs_long(&attribs);
- + }
- + printf("\n");
- +
- + XFree(visuals);
- +}
- +
- +#ifdef GLX_VERSION_1_3
- +
- +static void
- +print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode)
- +{
- + int numFBConfigs = 0;
- + struct visual_attribs attribs;
- + GLXFBConfig *fbconfigs;
- + int i;
- +
- + /* get list of all fbconfigs on this screen */
- + fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs);
- +
- + if (numFBConfigs == 0) {
- + XFree(fbconfigs);
- + return;
- + }
- +
- + printf("%d GLXFBConfigs:\n", numFBConfigs);
- + if (mode == Normal)
- + print_visual_attribs_short_header();
- + else if (mode == Wide)
- + print_visual_attribs_long_header();
- +
- + for (i = 0; i < numFBConfigs; i++) {
- + get_fbconfig_attribs(dpy, fbconfigs[i], &attribs);
- +
- + if (mode == Verbose)
- + print_visual_attribs_verbose(&attribs);
- + else if (mode == Normal)
- + print_visual_attribs_short(&attribs);
- + else if (mode == Wide)
- + print_visual_attribs_long(&attribs);
- + }
- + printf("\n");
- +
- + XFree(fbconfigs);
- +}
- +
- +#endif
- +
- +/*
- + * Stand-alone Mesa doesn't really implement the GLX protocol so it
- + * doesn't really know the GLX attributes associated with an X visual.
- + * The first time a visual is presented to Mesa's pseudo-GLX it
- + * attaches ancilliary buffers to it (like depth and stencil).
- + * But that usually only works if glXChooseVisual is used.
- + * This function calls glXChooseVisual() to sort of "prime the pump"
- + * for Mesa's GLX so that the visuals that get reported actually
- + * reflect what applications will see.
- + * This has no effect when using true GLX.
- + */
- +static void
- +mesa_hack(Display *dpy, int scrnum)
- +{
- + static int attribs[] = {
- + GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 1,
- + GLX_STENCIL_SIZE, 1,
- + GLX_ACCUM_RED_SIZE, 1,
- + GLX_ACCUM_GREEN_SIZE, 1,
- + GLX_ACCUM_BLUE_SIZE, 1,
- + GLX_ACCUM_ALPHA_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None
- + };
- + XVisualInfo *visinfo;
- +
- + visinfo = glXChooseVisual(dpy, scrnum, attribs);
- + if (visinfo)
- + XFree(visinfo);
- +}
- +
- +
- +/*
- + * Examine all visuals to find the so-called best one.
- + * We prefer deepest RGBA buffer with depth, stencil and accum
- + * that has no caveats.
- + */
- +static int
- +find_best_visual(Display *dpy, int scrnum)
- +{
- + XVisualInfo theTemplate;
- + XVisualInfo *visuals;
- + int numVisuals;
- + long mask;
- + int i;
- + struct visual_attribs bestVis;
- +
- + /* get list of all visuals on this screen */
- + theTemplate.screen = scrnum;
- + mask = VisualScreenMask;
- + visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
- +
- + /* init bestVis with first visual info */
- + get_visual_attribs(dpy, &visuals[0], &bestVis);
- +
- + /* try to find a "better" visual */
- + for (i = 1; i < numVisuals; i++) {
- + struct visual_attribs vis;
- +
- + get_visual_attribs(dpy, &visuals[i], &vis);
- +
- + /* always skip visuals with caveats */
- + if (vis.visualCaveat != GLX_NONE_EXT)
- + continue;
- +
- + /* see if this vis is better than bestVis */
- + if ((!bestVis.supportsGL && vis.supportsGL) ||
- + (bestVis.visualCaveat != GLX_NONE_EXT) ||
- + (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) ||
- + (!bestVis.doubleBuffer && vis.doubleBuffer) ||
- + (bestVis.redSize < vis.redSize) ||
- + (bestVis.greenSize < vis.greenSize) ||
- + (bestVis.blueSize < vis.blueSize) ||
- + (bestVis.alphaSize < vis.alphaSize) ||
- + (bestVis.depthSize < vis.depthSize) ||
- + (bestVis.stencilSize < vis.stencilSize) ||
- + (bestVis.accumRedSize < vis.accumRedSize)) {
- + /* found a better visual */
- + bestVis = vis;
- + }
- + }
- +
- + XFree(visuals);
- +
- + return bestVis.id;
- +}
- +
- +
- +static void
- +usage(void)
- +{
- + printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
- + printf("\t-v: Print visuals info in verbose form.\n");
- + printf("\t-t: Print verbose table.\n");
- + printf("\t-display <dname>: Print GLX visuals on specified server.\n");
- + printf("\t-h: This information.\n");
- + printf("\t-i: Force an indirect rendering context.\n");
- + printf("\t-b: Find the 'best' visual and print its number.\n");
- + printf("\t-l: Print interesting OpenGL limits.\n");
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + char *displayName = NULL;
- + Display *dpy;
- + int numScreens, scrnum;
- + InfoMode mode = Normal;
- + GLboolean findBest = GL_FALSE;
- + GLboolean limits = GL_FALSE;
- + Bool allowDirect = True;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
- + displayName = argv[i + 1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-t") == 0) {
- + mode = Wide;
- + }
- + else if (strcmp(argv[i], "-v") == 0) {
- + mode = Verbose;
- + }
- + else if (strcmp(argv[i], "-b") == 0) {
- + findBest = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-i") == 0) {
- + allowDirect = False;
- + }
- + else if (strcmp(argv[i], "-l") == 0) {
- + limits = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-h") == 0) {
- + usage();
- + return 0;
- + }
- + else {
- + printf("Unknown option `%s'\n", argv[i]);
- + usage();
- + return 0;
- + }
- + }
- +
- + dpy = XOpenDisplay(displayName);
- + if (!dpy) {
- + fprintf(stderr, "Error: unable to open display %s\n", XDisplayName(displayName));
- + return -1;
- + }
- +
- + if (findBest) {
- + int b;
- + mesa_hack(dpy, 0);
- + b = find_best_visual(dpy, 0);
- + printf("%d\n", b);
- + }
- + else {
- + numScreens = ScreenCount(dpy);
- + print_display_info(dpy);
- + for (scrnum = 0; scrnum < numScreens; scrnum++) {
- + mesa_hack(dpy, scrnum);
- + print_screen_info(dpy, scrnum, allowDirect, limits);
- + printf("\n");
- + print_visual_info(dpy, scrnum, mode);
- +#ifdef GLX_VERSION_1_3
- + print_fbconfig_info(dpy, scrnum, mode);
- +#endif
- + if (scrnum + 1 < numScreens)
- + printf("\n\n");
- + }
- + }
- +
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxpbdemo.c Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c
- --- Mesa-7.8.1/progs/xdemos/glxpbdemo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,431 @@
- +
- +/*
- + * This program demonstrates how to do "off-screen" rendering using
- + * the GLX pixel buffer extension.
- + *
- + * Written by Brian Paul for the "OpenGL and Window System Integration"
- + * course presented at SIGGRAPH '97. Updated on 5 October 2002.
- + *
- + * Updated on 31 January 2004 to use native GLX by
- + * Andrew P. Lentvorski, Jr. <bsder@allcaps.org>
- + *
- + * Usage:
- + * glxpbdemo width height imgfile
- + * Where:
- + * width is the width, in pixels, of the image to generate.
- + * height is the height, in pixels, of the image to generate.
- + * imgfile is the name of the PPM image file to write.
- + *
- + *
- + * This demo draws 3-D boxes with random orientation.
- + *
- + * On machines such as the SGI Indigo you may have to reconfigure your
- + * display/X server to enable pbuffers. Look in the /usr/gfx/ucode/MGRAS/vof/
- + * directory for display configurations with the _pbuf suffix. Use
- + * setmon -x <vof> to configure your X server and display for pbuffers.
- + *
- + * O2 systems seem to support pbuffers well.
- + *
- + */
- +
- +#include <string.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <X11/Xlib.h>
- +#include <GL/glx.h>
- +
- +/* Some ugly global vars */
- +static GLXFBConfig gFBconfig = 0;
- +static Display *gDpy = NULL;
- +static int gScreen = 0;
- +static GLXPbuffer gPBuffer = 0;
- +static int gWidth, gHeight;
- +
- +
- +/*
- + * Test for appropriate version of GLX to run this program
- + * Input: dpy - the X display
- + * screen - screen number
- + * Return: 0 = GLX not available.
- + * 1 = GLX available.
- + */
- +static int
- +RuntimeQueryGLXVersion(Display *dpy, int screen)
- +{
- +#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4)
- + char *glxversion;
- +
- + glxversion = (char *) glXGetClientString(dpy, GLX_VERSION);
- + if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4")))
- + return 0;
- +
- + glxversion = (char *) glXQueryServerString(dpy, screen, GLX_VERSION);
- + if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4")))
- + return 0;
- +
- + return 1;
- +#else
- + return 0;
- +#endif
- +}
- +
- +
- +
- +/*
- + * Create the pbuffer and return a GLXPbuffer handle.
- + */
- +static GLXPbuffer
- +MakePbuffer( Display *dpy, int screen, int width, int height )
- +{
- + GLXFBConfig *fbConfigs;
- + GLXFBConfig chosenFBConfig;
- + GLXPbuffer pBuffer = None;
- +
- + int nConfigs;
- + int fbconfigid;
- +
- + int fbAttribs[] = {
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_DEPTH_SIZE, 1,
- + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_PBUFFER_BIT,
- + None
- + };
- +
- + int pbAttribs[] = {
- + GLX_PBUFFER_WIDTH, 0,
- + GLX_PBUFFER_HEIGHT, 0,
- + GLX_LARGEST_PBUFFER, False,
- + GLX_PRESERVED_CONTENTS, False,
- + None
- + };
- +
- + pbAttribs[1] = width;
- + pbAttribs[3] = height;
- +
- + fbConfigs = glXChooseFBConfig(dpy, screen, fbAttribs, &nConfigs);
- +
- + if (0 == nConfigs || !fbConfigs) {
- + printf("Error: glxChooseFBConfig failed\n");
- + XFree(fbConfigs);
- + XCloseDisplay(dpy);
- + return 0;
- + }
- +
- + chosenFBConfig = fbConfigs[0];
- +
- + glXGetFBConfigAttrib(dpy, chosenFBConfig, GLX_FBCONFIG_ID, &fbconfigid);
- + printf("Chose 0x%x as fbconfigid\n", fbconfigid);
- +
- + /* Create the pbuffer using first fbConfig in the list that works. */
- + pBuffer = glXCreatePbuffer(dpy, chosenFBConfig, pbAttribs);
- +
- + if (pBuffer) {
- + gFBconfig = chosenFBConfig;
- + gWidth = width;
- + gHeight = height;
- + }
- +
- + XFree(fbConfigs);
- +
- + return pBuffer;
- +}
- +
- +
- +
- +/*
- + * Do all the X / GLX setup stuff.
- + */
- +static int
- +Setup(int width, int height)
- +{
- +#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4)
- + GLXContext glCtx;
- +
- + /* Open the X display */
- + gDpy = XOpenDisplay(NULL);
- + if (!gDpy) {
- + printf("Error: couldn't open default X display.\n");
- + return 0;
- + }
- +
- + /* Get default screen */
- + gScreen = DefaultScreen(gDpy);
- +
- + /* Test that GLX is available */
- + if (!RuntimeQueryGLXVersion(gDpy, gScreen)) {
- + printf("Error: GLX 1.3 or 1.4 not available\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Create Pbuffer */
- + gPBuffer = MakePbuffer( gDpy, gScreen, width, height );
- + if (gPBuffer==None) {
- + printf("Error: couldn't create pbuffer\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Create GLX context */
- + glCtx = glXCreateNewContext(gDpy, gFBconfig, GLX_RGBA_TYPE, NULL, True);
- + if (glCtx) {
- + if (!glXIsDirect(gDpy, glCtx)) {
- + printf("Warning: using indirect GLXContext\n");
- + }
- + }
- + else {
- + printf("Error: Couldn't create GLXContext\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Bind context to pbuffer */
- + if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) {
- + printf("Error: glXMakeCurrent failed\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + return 1; /* Success!! */
- +#else
- + printf("Error: GLX version 1.3 or 1.4 not available at compile time\n");
- + return 0;
- +#endif
- +}
- +
- +
- +
- +/* One-time GL setup */
- +static void
- +InitGL(void)
- +{
- + static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0};
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_NORMALIZE);
- + glEnable(GL_DEPTH_TEST);
- + glEnable(GL_CULL_FACE);
- +
- + glViewport(0, 0, gWidth, gHeight);
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
- + glMatrixMode( GL_MODELVIEW );
- + glLoadIdentity();
- + glTranslatef( 0.0, 0.0, -15.0 );
- +
- +}
- +
- +
- +/* Return random float in [0,1] */
- +static float
- +Random(void)
- +{
- + int i = rand();
- + return (float) (i % 1000) / 1000.0;
- +}
- +
- +
- +static void
- +RandomColor(void)
- +{
- + GLfloat c[4];
- + c[0] = Random();
- + c[1] = Random();
- + c[2] = Random();
- + c[3] = 1.0;
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);
- +}
- +
- +
- +/* This function borrowed from Mark Kilgard's GLUT */
- +static void
- +drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1,
- + GLfloat z0, GLfloat z1, GLenum type)
- +{
- + static GLfloat n[6][3] =
- + {
- + {-1.0, 0.0, 0.0},
- + {0.0, 1.0, 0.0},
- + {1.0, 0.0, 0.0},
- + {0.0, -1.0, 0.0},
- + {0.0, 0.0, 1.0},
- + {0.0, 0.0, -1.0}
- + };
- + static GLint faces[6][4] =
- + {
- + {0, 1, 2, 3},
- + {3, 2, 6, 7},
- + {7, 6, 5, 4},
- + {4, 5, 1, 0},
- + {5, 6, 2, 1},
- + {7, 4, 0, 3}
- + };
- + GLfloat v[8][3], tmp;
- + GLint i;
- +
- + if (x0 > x1) {
- + tmp = x0;
- + x0 = x1;
- + x1 = tmp;
- + }
- + if (y0 > y1) {
- + tmp = y0;
- + y0 = y1;
- + y1 = tmp;
- + }
- + if (z0 > z1) {
- + tmp = z0;
- + z0 = z1;
- + z1 = tmp;
- + }
- + v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
- + v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
- + v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
- + v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
- + v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
- + v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
- +
- + for (i = 0; i < 6; i++) {
- + glBegin(type);
- + glNormal3fv(&n[i][0]);
- + glVertex3fv(&v[faces[i][0]][0]);
- + glVertex3fv(&v[faces[i][1]][0]);
- + glVertex3fv(&v[faces[i][2]][0]);
- + glVertex3fv(&v[faces[i][3]][0]);
- + glEnd();
- + }
- +}
- +
- +
- +
- +/* Render a scene */
- +static void
- +Render(void)
- +{
- + int NumBoxes = 100;
- + int i;
- +
- + InitGL();
- + glClearColor(0.2, 0.2, 0.9, 0.0);
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + for (i=0;i<NumBoxes;i++) {
- + float tx = -2.0 + 4.0 * Random();
- + float ty = -2.0 + 4.0 * Random();
- + float tz = 4.0 - 16.0 * Random();
- + float sx = 0.1 + Random() * 0.4;
- + float sy = 0.1 + Random() * 0.4;
- + float sz = 0.1 + Random() * 0.4;
- + float rx = Random();
- + float ry = Random();
- + float rz = Random();
- + float ra = Random() * 360.0;
- + glPushMatrix();
- + glTranslatef(tx, ty, tz);
- + glRotatef(ra, rx, ry, rz);
- + glScalef(sx, sy, sz);
- + RandomColor();
- + drawBox(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, GL_POLYGON);
- + glPopMatrix();
- + }
- +
- + glFinish();
- +}
- +
- +
- +
- +static void
- +WriteFile(const char *filename)
- +{
- + FILE *f;
- + GLubyte *image;
- + int i;
- +
- + image = malloc(gWidth * gHeight * 3 * sizeof(GLubyte));
- + if (!image) {
- + printf("Error: couldn't allocate image buffer\n");
- + return;
- + }
- +
- + glPixelStorei(GL_PACK_ALIGNMENT, 1);
- + glReadPixels(0, 0, gWidth, gHeight, GL_RGB, GL_UNSIGNED_BYTE, image);
- +
- + f = fopen(filename, "w");
- + if (!f) {
- + printf("Couldn't open image file: %s\n", filename);
- + return;
- + }
- + fprintf(f,"P6\n");
- + fprintf(f,"# ppm-file created by %s\n", "trdemo2");
- + fprintf(f,"%i %i\n", gWidth, gHeight);
- + fprintf(f,"255\n");
- + fclose(f);
- + f = fopen(filename, "ab"); /* now append binary data */
- + if (!f) {
- + printf("Couldn't append to image file: %s\n", filename);
- + return;
- + }
- +
- + for (i=0;i<gHeight;i++) {
- + GLubyte *rowPtr;
- + /* Remember, OpenGL images are bottom to top. Have to reverse. */
- + rowPtr = image + (gHeight-1-i) * gWidth*3;
- + fwrite(rowPtr, 1, gWidth*3, f);
- + }
- +
- + fclose(f);
- + free(image);
- +
- + printf("Wrote %d by %d image file: %s\n", gWidth, gHeight, filename);
- +}
- +
- +
- +
- +/*
- + * Print message describing command line parameters.
- + */
- +static void
- +Usage(const char *appName)
- +{
- + printf("Usage:\n");
- + printf(" %s width height imgfile\n", appName);
- + printf("Where imgfile is a ppm file\n");
- +}
- +
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + if (argc!=4) {
- + Usage(argv[0]);
- + }
- + else {
- + int width = atoi(argv[1]);
- + int height = atoi(argv[2]);
- + char *fileName = argv[3];
- + if (width<=0) {
- + printf("Error: width parameter must be at least 1.\n");
- + return 1;
- + }
- + if (height<=0) {
- + printf("Error: height parameter must be at least 1.\n");
- + return 1;
- + }
- + if (!Setup(width, height)) {
- + return 1;
- + }
- +
- + printf("Setup completed\n");
- + Render();
- + printf("Render completed.\n");
- + WriteFile(fileName);
- + printf("File write completed.\n");
- +
- + glXDestroyPbuffer( gDpy, gPBuffer );
- + }
- + return 0;
- +}
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxpixmap.c Mesa-7.8.1.patched/progs/xdemos/glxpixmap.c
- --- Mesa-7.8.1/progs/xdemos/glxpixmap.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxpixmap.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,187 @@
- +
- +
- +/*
- + * A demonstration of using the GLXPixmap functions. This program is in
- + * the public domain.
- + *
- + * Brian Paul
- + */
- +
- +
- +#include <GL/gl.h>
- +#define GLX_GLXEXT_PROTOTYPES
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +
- +
- +static GLXContext ctx;
- +static XVisualInfo *visinfo;
- +static GC gc;
- +
- +
- +
- +static Window make_rgb_window( Display *dpy,
- + unsigned int width, unsigned int height )
- +{
- + const int sbAttrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + None };
- + const int dbAttrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, (int *) sbAttrib );
- + if (!visinfo) {
- + visinfo = glXChooseVisual( dpy, scrnum, (int *) dbAttrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB visual\n");
- + exit(1);
- + }
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + /* TODO: share root colormap if possible */
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* make an X GC so we can do XCopyArea later */
- + gc = XCreateGC( dpy, win, 0, NULL );
- +
- + /* need indirect context */
- + ctx = glXCreateContext( dpy, visinfo, NULL, False );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(-1);
- + }
- +
- + printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
- +
- + return win;
- +}
- +
- +
- +static GLXPixmap make_pixmap( Display *dpy, Window win,
- + unsigned int width, unsigned int height,
- + Pixmap *pixmap)
- +{
- + Pixmap pm;
- + GLXPixmap glxpm;
- + XWindowAttributes attr;
- +
- + pm = XCreatePixmap( dpy, win, width, height, visinfo->depth );
- + if (!pm) {
- + printf("Error: XCreatePixmap failed\n");
- + exit(-1);
- + }
- +
- + XGetWindowAttributes( dpy, win, &attr );
- +
- + /*
- + * IMPORTANT:
- + * Use the glXCreateGLXPixmapMESA funtion when using Mesa because
- + * Mesa needs to know the colormap associated with a pixmap in order
- + * to render correctly. This is because Mesa allows RGB rendering
- + * into any kind of visual, not just TrueColor or DirectColor.
- + */
- +#ifdef GLX_MESA_pixmap_colormap
- + if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) {
- + /* stand-alone Mesa, specify the colormap */
- + glxpm = glXCreateGLXPixmapMESA( dpy, visinfo, pm, attr.colormap );
- + }
- + else {
- + glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
- + }
- +#else
- + /* This will work with Mesa too if the visual is TrueColor or DirectColor */
- + glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
- +#endif
- +
- + if (!glxpm) {
- + printf("Error: GLXCreateGLXPixmap failed\n");
- + exit(-1);
- + }
- +
- + *pixmap = pm;
- +
- + return glxpm;
- +}
- +
- +
- +
- +static void event_loop( Display *dpy, GLXPixmap pm )
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent( dpy, &event );
- +
- + switch (event.type) {
- + case Expose:
- + printf("Redraw\n");
- + /* copy the image from GLXPixmap to window */
- + XCopyArea( dpy, pm, event.xany.window, /* src, dest */
- + gc, 0, 0, 300, 300, /* gc, src pos, size */
- + 0, 0 ); /* dest pos */
- + break;
- + case ConfigureNotify:
- + /* nothing */
- + break;
- + }
- + }
- +}
- +
- +
- +
- +int main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + Window win;
- + Pixmap pm;
- + GLXPixmap glxpm;
- +
- + dpy = XOpenDisplay(NULL);
- +
- + win = make_rgb_window( dpy, 300, 300 );
- + glxpm = make_pixmap( dpy, win, 300, 300, &pm );
- +
- + glXMakeCurrent( dpy, glxpm, ctx );
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- +
- + /* Render an image into the pixmap */
- + glShadeModel( GL_FLAT );
- + glClearColor( 0.5, 0.5, 0.5, 1.0 );
- + glClear( GL_COLOR_BUFFER_BIT );
- + glViewport( 0, 0, 300, 300 );
- + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
- + glColor3f( 0.0, 1.0, 1.0 );
- + glRectf( -0.75, -0.75, 0.75, 0.75 );
- + glFlush();
- + glXWaitGL();
- +
- + XMapWindow( dpy, win );
- +
- + event_loop( dpy, pm );
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxsnoop.c Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c
- --- Mesa-7.8.1/progs/xdemos/glxsnoop.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,377 @@
- +/**
- + * Display/snoop the z/stencil/back/front buffers of another app's window.
- + * Also, an example of the need for shared ancillary renderbuffers.
- + *
- + * Hint: use 'xwininfo' to get a window's ID.
- + *
- + * Brian Paul
- + * 11 Oct 2007
- + */
- +
- +#define GL_GLEXT_PROTOTYPES
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <X11/keysym.h>
- +
- +
- +#define Z_BUFFER 1
- +#define STENCIL_BUFFER 2
- +#define BACK_BUFFER 3
- +#define FRONT_BUFFER 4
- +
- +
- +static int Buffer = BACK_BUFFER;
- +static int WindowID = 0;
- +static const char *DisplayName = NULL;
- +static GLXContext Context = 0;
- +static int Width, Height;
- +
- +
- +/**
- + * Grab the z/stencil/back/front image from the srcWin and display it
- + * (possibly converted to grayscale) in the dstWin.
- + */
- +static void
- +redraw(Display *dpy, Window srcWin, Window dstWin )
- +{
- + GLubyte *image = malloc(Width * Height * 4);
- +
- + glXMakeCurrent(dpy, srcWin, Context);
- + glPixelStorei(GL_PACK_ALIGNMENT, 1);
- + if (Buffer == BACK_BUFFER) {
- + glReadBuffer(GL_BACK);
- + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
- + }
- + else if (Buffer == FRONT_BUFFER) {
- + glReadBuffer(GL_FRONT);
- + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
- + }
- + else if (Buffer == Z_BUFFER) {
- + GLfloat *z = malloc(Width * Height * sizeof(GLfloat));
- + int i;
- + glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z);
- + for (i = 0; i < Width * Height; i++) {
- + image[i*4+0] =
- + image[i*4+1] =
- + image[i*4+2] = (GLint) (255.0 * z[i]);
- + image[i*4+3] = 255;
- + }
- + free(z);
- + }
- + else if (Buffer == STENCIL_BUFFER) {
- + GLubyte *sten = malloc(Width * Height * sizeof(GLubyte));
- + int i, min = 100, max = -1;
- + float step;
- + int sz;
- + glGetIntegerv(GL_STENCIL_BITS, &sz);
- + glReadPixels(0, 0, Width, Height,
- + GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten);
- + /* find min/max for converting stencil to grayscale */
- + for (i = 0; i < Width * Height; i++) {
- + if (sten[i] < min)
- + min = sten[i];
- + if (sten[i] > max)
- + max = sten[i];
- + }
- + if (min == max)
- + step = 0;
- + else
- + step = 255.0 / (float) (max - min);
- + for (i = 0; i < Width * Height; i++) {
- + image[i*4+0] =
- + image[i*4+1] =
- + image[i*4+2] = (GLint) ((sten[i] - min) * step);
- + image[i*4+3] = 255;
- + }
- + free(sten);
- + }
- +
- + glXMakeCurrent(dpy, dstWin, Context);
- + glWindowPos2iARB(0, 0);
- + glDrawBuffer(GL_FRONT);
- + glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
- + glFlush();
- +
- + free(image);
- +}
- +
- +
- +static void
- +set_window_title(Display *dpy, Window win, const char *title)
- +{
- + XSizeHints sizehints;
- + sizehints.flags = 0;
- + XSetStandardProperties(dpy, win, title, title,
- + None, (char **)NULL, 0, &sizehints);
- +}
- +
- +
- +static Window
- +make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
- +{
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + int x = 0, y = 0;
- + char *name = NULL;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, x, y, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + return win;
- +}
- +
- +
- +static void
- +update_window_title(Display *dpy, Window win)
- +{
- + char title[1000], *buf;
- +
- + switch (Buffer) {
- + case Z_BUFFER:
- + buf = "Z";
- + break;
- + case STENCIL_BUFFER:
- + buf = "Stencil";
- + break;
- + case BACK_BUFFER:
- + buf = "Back";
- + break;
- + case FRONT_BUFFER:
- + buf = "Front";
- + break;
- + default:
- + buf = "";
- + }
- +
- + sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf);
- +
- + set_window_title(dpy, win, title);
- +}
- +
- +
- +static void
- +keypress(Display *dpy, Window win, char key)
- +{
- + switch (key) {
- + case 27:
- + /* escape */
- + exit(0);
- + break;
- + case 's':
- + Buffer = STENCIL_BUFFER;
- + break;
- + case 'z':
- + Buffer = Z_BUFFER;
- + break;
- + case 'f':
- + Buffer = FRONT_BUFFER;
- + break;
- + case 'b':
- + Buffer = BACK_BUFFER;
- + break;
- + default:
- + return;
- + }
- +
- + update_window_title(dpy, win);
- + redraw(dpy, WindowID, win);
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, Window win)
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent( dpy, &event );
- +
- + switch (event.type) {
- + case Expose:
- + redraw(dpy, WindowID, win);
- + break;
- + case ConfigureNotify:
- + /*resize( event.xconfigure.width, event.xconfigure.height );*/
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + keypress(dpy, win, buffer[0]);
- + }
- + }
- + default:
- + /* nothing */
- + ;
- + }
- + }
- +}
- +
- +
- +static VisualID
- +get_window_visualid(Display *dpy, Window win)
- +{
- + XWindowAttributes attr;
- +
- + if (XGetWindowAttributes(dpy, win, &attr)) {
- + return attr.visual->visualid;
- + }
- + else {
- + return 0;
- + }
- +}
- +
- +
- +static void
- +get_window_size(Display *dpy, Window win, int *w, int *h)
- +{
- + XWindowAttributes attr;
- +
- + if (XGetWindowAttributes(dpy, win, &attr)) {
- + *w = attr.width;
- + *h = attr.height;
- + }
- + else {
- + *w = *h = 0;
- + }
- +}
- +
- +
- +static XVisualInfo *
- +visualid_to_visualinfo(Display *dpy, VisualID vid)
- +{
- + XVisualInfo *vinfo, templ;
- + long mask;
- + int n;
- +
- + templ.visualid = vid;
- + mask = VisualIDMask;
- +
- + vinfo = XGetVisualInfo(dpy, mask, &templ, &n);
- + return vinfo;
- +}
- +
- +
- +static void
- +key_usage(void)
- +{
- + printf("Keyboard:\n");
- + printf(" z - display Z buffer\n");
- + printf(" s - display stencil buffer\n");
- + printf(" f - display front color buffer\n");
- + printf(" b - display back buffer\n");
- +}
- +
- +
- +static void
- +usage(void)
- +{
- + printf("Usage: glxsnoop [-display dpy] windowID\n");
- + key_usage();
- +}
- +
- +
- +static void
- +parse_opts(int argc, char *argv[])
- +{
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-h") == 0) {
- + usage();
- + exit(0);
- + }
- + else if (strcmp(argv[i], "-display") == 0) {
- + DisplayName = argv[i + 1];
- + i++;
- + }
- + else {
- + if (argv[i][0] == '0' && argv[i][1] == 'x') {
- + /* hex */
- + WindowID = strtol(argv[i], NULL, 16);
- + }
- + else {
- + WindowID = atoi(argv[i]);
- + }
- + break;
- + }
- + }
- +
- + if (!WindowID) {
- + usage();
- + exit(0);
- + }
- +}
- +
- +
- +int
- +main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + VisualID vid;
- + XVisualInfo *visinfo;
- + Window win;
- +
- + parse_opts(argc, argv);
- +
- + key_usage();
- +
- + dpy = XOpenDisplay(DisplayName);
- +
- + /* find the VisualID for the named window */
- + vid = get_window_visualid(dpy, WindowID);
- + get_window_size(dpy, WindowID, &Width, &Height);
- +
- + visinfo = visualid_to_visualinfo(dpy, vid);
- +
- + Context = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!Context) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + win = make_gl_window(dpy, visinfo, Width, Height);
- + XMapWindow(dpy, win);
- + update_window_title(dpy, win);
- +
- + event_loop( dpy, win );
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/glxswapcontrol.c Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c
- --- Mesa-7.8.1/progs/xdemos/glxswapcontrol.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,893 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/*
- + * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
- + * Port by Brian Paul 23 March 2001
- + *
- + * Modified by Ian Romanick <idr@us.ibm.com> 09 April 2003 to support
- + * GLX_{MESA,SGI}_swap_control and GLX_OML_sync_control.
- + *
- + * Command line options:
- + * -display Name of the display to use.
- + * -info print GL implementation information
- + * -swap N Attempt to set the swap interval to 1/N second
- + * -forcegetrate Get the display refresh rate even if the required GLX
- + * extension is not supported.
- + */
- +
- +
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#ifndef __VMS
- +/*# include <stdint.h>*/
- +#endif
- +# define GLX_GLXEXT_PROTOTYPES
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +
- +#ifndef GLX_MESA_swap_control
- +typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval);
- +typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void );
- +#endif
- +
- +#if !defined( GLX_OML_sync_control ) && defined( _STDINT_H )
- +#define GLX_OML_sync_control 1
- +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
- +#endif
- +
- +#ifndef GLX_MESA_swap_frame_usage
- +#define GLX_MESA_swap_frame_usage 1
- +typedef int ( * PFNGLXGETFRAMEUSAGEMESAPROC) (Display *dpy, GLXDrawable drawable, float * usage );
- +#endif
- +
- +#define BENCHMARK
- +
- +PFNGLXGETFRAMEUSAGEMESAPROC get_frame_usage = NULL;
- +
- +#ifdef BENCHMARK
- +
- +/* XXX this probably isn't very portable */
- +
- +#include <sys/time.h>
- +#include <unistd.h>
- +
- +#define NUL '\0'
- +
- +/* return current time (in seconds) */
- +static int
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (int) tv.tv_sec;
- +}
- +
- +#else /*BENCHMARK*/
- +
- +/* dummy */
- +static int
- +current_time(void)
- +{
- + return 0;
- +}
- +
- +#endif /*BENCHMARK*/
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
- +static GLint gear1, gear2, gear3;
- +static GLfloat angle = 0.0;
- +
- +static GLboolean has_OML_sync_control = GL_FALSE;
- +static GLboolean has_SGI_swap_control = GL_FALSE;
- +static GLboolean has_MESA_swap_control = GL_FALSE;
- +static GLboolean has_MESA_swap_frame_usage = GL_FALSE;
- +
- +static char ** extension_table = NULL;
- +static unsigned num_extensions;
- +
- +static GLboolean use_ztrick = GL_FALSE;
- +static GLfloat aspectX = 1.0f, aspectY = 1.0f;
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +draw(void)
- +{
- + if ( use_ztrick ) {
- + static GLboolean flip = GL_FALSE;
- + static const GLfloat vert[4][3] = {
- + { -1, -1, -0.999 },
- + { 1, -1, -0.999 },
- + { 1, 1, -0.999 },
- + { -1, 1, -0.999 }
- + };
- + static const GLfloat col[4][3] = {
- + { 1.0, 0.6, 0.0 },
- + { 1.0, 0.6, 0.0 },
- + { 0.0, 0.0, 0.0 },
- + { 0.0, 0.0, 0.0 },
- + };
- +
- + if ( flip ) {
- + glDepthRange(0, 0.5);
- + glDepthFunc(GL_LEQUAL);
- + }
- + else {
- + glDepthRange(1.0, 0.4999);
- + glDepthFunc(GL_GEQUAL);
- + }
- +
- + flip = !flip;
- +
- + /* The famous Quake "Z trick" only works when the whole screen is
- + * re-drawn each frame.
- + */
- +
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1, 1, -1, 1, -1, 1);
- + glDisable(GL_LIGHTING);
- + glShadeModel(GL_SMOOTH);
- +
- + glEnableClientState( GL_VERTEX_ARRAY );
- + glEnableClientState( GL_COLOR_ARRAY );
- + glVertexPointer( 3, GL_FLOAT, 0, vert );
- + glColorPointer( 3, GL_FLOAT, 0, col );
- + glDrawArrays( GL_POLYGON, 0, 4 );
- + glDisableClientState( GL_COLOR_ARRAY );
- + glDisableClientState( GL_VERTEX_ARRAY );
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);
- +
- + glEnable(GL_LIGHTING);
- +
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -45.0);
- + }
- + else {
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- + }
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + glPushMatrix();
- + glTranslatef(-3.0, -2.0, 0.0);
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(3.1, -2.0, 0.0);
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(-3.1, 4.2, 0.0);
- + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
- + glCallList(gear3);
- + glPopMatrix();
- +
- + glPopMatrix();
- +}
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(int width, int height)
- +{
- + if (width > height) {
- + aspectX = (GLfloat) width / (GLfloat) height;
- + aspectY = 1.0;
- + }
- + else {
- + aspectX = 1.0;
- + aspectY = (GLfloat) height / (GLfloat) width;
- + }
- +
- + glViewport(0, 0, (GLint) width, (GLint) height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- +
- + glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -45.0);
- +}
- +
- +
- +static void
- +init(void)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
- + static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_CULL_FACE);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + /* make the gears */
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(0.5, 2.0, 2.0, 10, 0.7);
- + glEndList();
- +
- + gear3 = glGenLists(1);
- + glNewList(gear3, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
- + gear(1.3, 2.0, 0.5, 10, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- +}
- +
- +
- +/**
- + * Remove window border/decorations.
- + */
- +static void
- +no_border( Display *dpy, Window w)
- +{
- + static const unsigned MWM_HINTS_DECORATIONS = (1 << 1);
- + static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5;
- +
- + typedef struct
- + {
- + unsigned long flags;
- + unsigned long functions;
- + unsigned long decorations;
- + long inputMode;
- + unsigned long status;
- + } PropMotifWmHints;
- +
- + PropMotifWmHints motif_hints;
- + Atom prop, proptype;
- + unsigned long flags = 0;
- +
- + /* setup the property */
- + motif_hints.flags = MWM_HINTS_DECORATIONS;
- + motif_hints.decorations = flags;
- +
- + /* get the atom for the property */
- + prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
- + if (!prop) {
- + /* something went wrong! */
- + return;
- + }
- +
- + /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
- + proptype = prop;
- +
- + XChangeProperty( dpy, w, /* display, window */
- + prop, proptype, /* property, type */
- + 32, /* format: 32-bit datums */
- + PropModeReplace, /* mode */
- + (unsigned char *) &motif_hints, /* data */
- + PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */
- + );
- +}
- +
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height, GLboolean fullscreen,
- + Window *winRet, GLXContext *ctxRet)
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + if (fullscreen) {
- + x = y = 0;
- + width = DisplayWidth( dpy, scrnum );
- + height = DisplayHeight( dpy, scrnum );
- + }
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + if (fullscreen)
- + no_border(dpy, win);
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + XFree(visinfo);
- +
- + *winRet = win;
- + *ctxRet = ctx;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, Window win)
- +{
- + float frame_usage = 0.0;
- +
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + /* we'll redraw below */
- + break;
- + case ConfigureNotify:
- + reshape(event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- + }
- + }
- + }
- + }
- + }
- +
- + /* next frame */
- + angle += 2.0;
- +
- + draw();
- +
- + glXSwapBuffers(dpy, win);
- +
- + if ( get_frame_usage != NULL ) {
- + GLfloat temp;
- +
- + (*get_frame_usage)( dpy, win, & temp );
- + frame_usage += temp;
- + }
- +
- + /* calc framerate */
- + {
- + static int t0 = -1;
- + static int frames = 0;
- + int t = current_time();
- +
- + if (t0 < 0)
- + t0 = t;
- +
- + frames++;
- +
- + if (t - t0 >= 5.0) {
- + GLfloat seconds = t - t0;
- + GLfloat fps = frames / seconds;
- + if ( get_frame_usage != NULL ) {
- + printf("%d frames in %3.1f seconds = %6.3f FPS (%3.1f%% usage)\n",
- + frames, seconds, fps,
- + (frame_usage * 100.0) / (float) frames );
- + }
- + else {
- + printf("%d frames in %3.1f seconds = %6.3f FPS\n",
- + frames, seconds, fps);
- + }
- +
- + t0 = t;
- + frames = 0;
- + frame_usage = 0.0;
- + }
- + }
- + }
- +}
- +
- +
- +/**
- + * Display the refresh rate of the display using the GLX_OML_sync_control
- + * extension.
- + */
- +static void
- +show_refresh_rate( Display * dpy )
- +{
- +#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
- + PFNGLXGETMSCRATEOMLPROC get_msc_rate;
- + int32_t n;
- + int32_t d;
- +
- + get_msc_rate = (PFNGLXGETMSCRATEOMLPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetMscRateOML" );
- + if ( get_msc_rate != NULL ) {
- + (*get_msc_rate)( dpy, glXGetCurrentDrawable(), &n, &d );
- + printf( "refresh rate: %.1fHz\n", (float) n / d );
- + return;
- + }
- +#endif
- + printf( "glXGetMscRateOML not supported.\n" );
- +}
- +
- +
- +/**
- + * Fill in the table of extension strings from a supplied extensions string
- + * (as returned by glXQueryExtensionsString).
- + *
- + * \param string String of GLX extensions.
- + * \sa is_extension_supported
- + */
- +static void
- +make_extension_table( const char * string )
- +{
- + char ** string_tab;
- + unsigned num_strings;
- + unsigned base;
- + unsigned idx;
- + unsigned i;
- +
- + /* Count the number of spaces in the string. That gives a base-line
- + * figure for the number of extension in the string.
- + */
- +
- + num_strings = 1;
- + for ( i = 0 ; string[i] != NUL ; i++ ) {
- + if ( string[i] == ' ' ) {
- + num_strings++;
- + }
- + }
- +
- + string_tab = (char **) malloc( sizeof( char * ) * num_strings );
- + if ( string_tab == NULL ) {
- + return;
- + }
- +
- + base = 0;
- + idx = 0;
- +
- + while ( string[ base ] != NUL ) {
- + /* Determine the length of the next extension string.
- + */
- +
- + for ( i = 0
- + ; (string[ base + i ] != NUL) && (string[ base + i ] != ' ')
- + ; i++ ) {
- + /* empty */ ;
- + }
- +
- + if ( i > 0 ) {
- + /* If the string was non-zero length, add it to the table. We
- + * can get zero length strings if there is a space at the end of
- + * the string or if there are two (or more) spaces next to each
- + * other in the string.
- + */
- +
- + string_tab[ idx ] = malloc( sizeof( char ) * (i + 1) );
- + if ( string_tab[ idx ] == NULL ) {
- + return;
- + }
- +
- + (void) memcpy( string_tab[ idx ], & string[ base ], i );
- + string_tab[ idx ][i] = NUL;
- + idx++;
- + }
- +
- +
- + /* Skip to the start of the next extension string.
- + */
- +
- + for ( base += i
- + ; (string[ base ] == ' ') && (string[ base ] != NUL)
- + ; base++ ) {
- + /* empty */ ;
- + }
- + }
- +
- + extension_table = string_tab;
- + num_extensions = idx;
- +}
- +
- +
- +/**
- + * Determine of an extension is supported. The extension string table
- + * must have already be initialized by calling \c make_extension_table.
- + *
- + * \praram ext Extension to be tested.
- + * \return GL_TRUE of the extension is supported, GL_FALSE otherwise.
- + * \sa make_extension_table
- + */
- +static GLboolean
- +is_extension_supported( const char * ext )
- +{
- + unsigned i;
- +
- + for ( i = 0 ; i < num_extensions ; i++ ) {
- + if ( strcmp( ext, extension_table[i] ) == 0 ) {
- + return GL_TRUE;
- + }
- + }
- +
- + return GL_FALSE;
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + char *dpyName = NULL;
- + int swap_interval = 1;
- + GLboolean do_swap_interval = GL_FALSE;
- + GLboolean force_get_rate = GL_FALSE;
- + GLboolean fullscreen = GL_FALSE;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- + PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL;
- + PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL;
- + int width = 300, height = 300;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) {
- + swap_interval = atoi( argv[i+1] );
- + do_swap_interval = GL_TRUE;
- + i++;
- + }
- + else if (strcmp(argv[i], "-forcegetrate") == 0) {
- + /* This option was put in because some DRI drivers don't support the
- + * full GLX_OML_sync_control extension, but they do support
- + * glXGetMscRateOML.
- + */
- + force_get_rate = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-fullscreen") == 0) {
- + fullscreen = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-ztrick") == 0) {
- + use_ztrick = GL_TRUE;
- + }
- + else if (strcmp(argv[i], "-help") == 0) {
- + printf("Usage:\n");
- + printf(" gears [options]\n");
- + printf("Options:\n");
- + printf(" -help Print this information\n");
- + printf(" -display displayName Specify X display\n");
- + printf(" -info Display GL information\n");
- + printf(" -swap N Swap no more than once per N vertical refreshes\n");
- + printf(" -forcegetrate Try to use glXGetMscRateOML function\n");
- + printf(" -fullscreen Full-screen window\n");
- + return 0;
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
- + return -1;
- + }
- +
- + make_window(dpy, "glxgears", 0, 0, width, height, fullscreen, &win, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, win, ctx);
- +
- + make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) );
- + has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" );
- + has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" );
- + has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" );
- + has_MESA_swap_frame_usage = is_extension_supported( "GLX_MESA_swap_frame_usage" );
- +
- + if ( has_MESA_swap_control ) {
- + set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalMESA" );
- + get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetSwapIntervalMESA" );
- + }
- + else if ( has_SGI_swap_control ) {
- + set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" );
- + }
- +
- +
- + if ( has_MESA_swap_frame_usage ) {
- + get_frame_usage = (PFNGLXGETFRAMEUSAGEMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetFrameUsageMESA" );
- + }
- +
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + if ( has_OML_sync_control || force_get_rate ) {
- + show_refresh_rate( dpy );
- + }
- +
- + if ( get_swap_interval != NULL ) {
- + printf("Default swap interval = %d\n", (*get_swap_interval)() );
- + }
- + }
- +
- + if ( do_swap_interval ) {
- + if ( set_swap_interval != NULL ) {
- + if ( ((swap_interval == 0) && !has_MESA_swap_control)
- + || (swap_interval < 0) ) {
- + printf( "Swap interval must be non-negative or greater than zero "
- + "if GLX_MESA_swap_control is not supported.\n" );
- + }
- + else {
- + (*set_swap_interval)( swap_interval );
- + }
- +
- + if ( printInfo && (get_swap_interval != NULL) ) {
- + printf("Current swap interval = %d\n", (*get_swap_interval)() );
- + }
- + }
- + else {
- + printf("Unable to set swap-interval. Neither GLX_SGI_swap_control "
- + "nor GLX_MESA_swap_control are supported.\n" );
- + }
- + }
- +
- + init();
- +
- + /* Set initial projection/viewing transformation.
- + * same as glxgears.c
- + */
- + reshape(width, height);
- +
- + event_loop(dpy, win);
- +
- + glXDestroyContext(dpy, ctx);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.c Mesa-7.8.1.patched/progs/xdemos/ipc.c
- --- Mesa-7.8.1/progs/xdemos/ipc.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/ipc.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,264 @@
- +/* Copyright (c) 2003 Tungsten Graphics, Inc.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining
- + * a copy of this software and associated documentation files ("the
- + * Software"), to deal in the Software without restriction, including
- + * without limitation the rights to use, copy, modify, merge, publish,
- + * distribute, sublicense, and/or sell copies of the Software, and to
- + * permit persons to whom the Software is furnished to do so, subject to
- + * the following conditions: The above copyright notice, the Tungsten
- + * Graphics splash screen, and this permission notice shall be included
- + * in all copies or substantial portions of the Software. THE SOFTWARE
- + * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
- + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
- + * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/*
- + * Simple IPC API
- + * Brian Paul
- + */
- +
- +
- +#include <assert.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <sys/types.h>
- +#include <netinet/in.h>
- +#include <netinet/tcp.h>
- +#include <arpa/inet.h>
- +#include <netdb.h>
- +#include <unistd.h>
- +#include <sys/socket.h>
- +#include "ipc.h"
- +
- +#if defined(IRIX) || defined(irix)
- +typedef int socklen_t;
- +#endif
- +
- +#define NO_DELAY 1
- +
- +#define DEFAULT_MASTER_PORT 7011
- +
- +
- +/*
- + * Return my hostname in <nameOut>.
- + * Return 1 for success, 0 for error.
- + */
- +int
- +MyHostName(char *nameOut, int maxNameLength)
- +{
- + int k = gethostname(nameOut, maxNameLength);
- + return k==0;
- +}
- +
- +
- +/*
- + * Create a socket attached to a port. Later, we can call AcceptConnection
- + * on the socket returned from this function.
- + * Return the new socket number or -1 if error.
- + */
- +int
- +CreatePort(int *port)
- +{
- + char hostname[1000];
- + struct sockaddr_in servaddr;
- + struct hostent *hp;
- + int so_reuseaddr = 1;
- + int tcp_nodelay = 1;
- + int sock, k;
- +
- + /* create socket */
- + sock = socket(AF_INET, SOCK_STREAM, 0);
- + assert(sock > 2);
- +
- + /* get my host name */
- + k = gethostname(hostname, 1000);
- + assert(k == 0);
- +
- + /* get hostent info */
- + hp = gethostbyname(hostname);
- + assert(hp);
- +
- + /* initialize the servaddr struct */
- + memset(&servaddr, 0, sizeof(servaddr) );
- + servaddr.sin_family = AF_INET;
- + servaddr.sin_port = htons((unsigned short) (*port));
- + memcpy((char *) &servaddr.sin_addr, hp->h_addr,
- + sizeof(servaddr.sin_addr));
- +
- + /* deallocate when we exit */
- + k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- + (char *) &so_reuseaddr, sizeof(so_reuseaddr));
- + assert(k==0);
- +
- + /* send packets immediately */
- +#if NO_DELAY
- + k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- + (char *) &tcp_nodelay, sizeof(tcp_nodelay));
- + assert(k==0);
- +#endif
- +
- + if (*port == 0)
- + *port = DEFAULT_MASTER_PORT;
- +
- + k = 1;
- + while (k && (*port < 65534)) {
- + /* bind our address to the socket */
- + servaddr.sin_port = htons((unsigned short) (*port));
- + k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
- + if (k)
- + *port = *port + 1;
- + }
- +
- +#if 0
- + printf("###### Real Port: %d\n", *port);
- +#endif
- +
- + /* listen for connections */
- + k = listen(sock, 100);
- + assert(k == 0);
- +
- + return sock;
- +}
- +
- +
- +/*
- + * Accept a connection on the named socket.
- + * Return a new socket for the new connection, or -1 if error.
- + */
- +int
- +AcceptConnection(int socket)
- +{
- + struct sockaddr addr;
- + socklen_t addrLen;
- + int newSock;
- +
- + addrLen = sizeof(addr);
- + newSock = accept(socket, &addr, &addrLen);
- + if (newSock == 1)
- + return -1;
- + else
- + return newSock;
- +}
- +
- +
- +/*
- + * Contact the server running on the given host on the named port.
- + * Return socket number or -1 if error.
- + */
- +int
- +Connect(const char *hostname, int port)
- +{
- + struct sockaddr_in servaddr;
- + struct hostent *hp;
- + int sock, k;
- + int tcp_nodelay = 1;
- +
- + assert(port);
- +
- + sock = socket(AF_INET, SOCK_STREAM, 0);
- + assert(sock >= 0);
- +
- + hp = gethostbyname(hostname);
- + assert(hp);
- +
- + memset(&servaddr, 0, sizeof(servaddr));
- + servaddr.sin_family = AF_INET;
- + servaddr.sin_port = htons((unsigned short) port);
- + memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
- +
- + k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
- + if (k != 0) {
- + perror("Connect:");
- + return -1;
- + }
- +
- +#if NO_DELAY
- + /* send packets immediately */
- + k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- + (char *) &tcp_nodelay, sizeof(tcp_nodelay));
- + assert(k==0);
- +#endif
- +
- + return sock;
- +}
- +
- +
- +void
- +CloseSocket(int socket)
- +{
- + close(socket);
- +}
- +
- +
- +int
- +SendData(int socket, const void *data, int bytes)
- +{
- + int sent = 0;
- + int b;
- +
- + while (sent < bytes) {
- + b = write(socket, (char *) data + sent, bytes - sent);
- + if (b <= 0)
- + return -1; /* something broke */
- + sent += b;
- + }
- + return sent;
- +}
- +
- +
- +int
- +ReceiveData(int socket, void *data, int bytes)
- +{
- + int received = 0, b;
- +
- + while (received < bytes) {
- + b = read(socket, (char *) data + received, bytes - received);
- + if (b <= 0)
- + return -1;
- + received += b;
- + }
- + return received;
- +}
- +
- +
- +int
- +SendString(int socket, const char *str)
- +{
- + const int len = strlen(str);
- + int sent, b;
- +
- + /* first, send a 4-byte length indicator */
- + b = write(socket, &len, sizeof(len));
- + if (b <= 0)
- + return -1;
- +
- + sent = SendData(socket, str, len);
- + assert(sent == len);
- + return sent;
- +}
- +
- +
- +int
- +ReceiveString(int socket, char *str, int maxLen)
- +{
- + int len, received, b;
- +
- + /* first, read 4 bytes to see how long of string to receive */
- + b = read(socket, &len, sizeof(len));
- + if (b <= 0)
- + return -1;
- +
- + assert(len <= maxLen); /* XXX fix someday */
- + assert(len >= 0);
- + received = ReceiveData(socket, str, len);
- + assert(received != -1);
- + assert(received == len);
- + str[len] = 0;
- + return received;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.h Mesa-7.8.1.patched/progs/xdemos/ipc.h
- --- Mesa-7.8.1/progs/xdemos/ipc.h 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/ipc.h 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,16 @@
- +#ifndef IPC_H
- +#define IPC_H
- +
- +
- +extern int MyHostName(char *nameOut, int maxNameLength);
- +extern int CreatePort(int *port);
- +extern int AcceptConnection(int socket);
- +extern int Connect(const char *hostname, int port);
- +extern void CloseSocket(int socket);
- +extern int SendData(int socket, const void *data, int bytes);
- +extern int ReceiveData(int socket, void *data, int bytes);
- +extern int SendString(int socket, const char *str);
- +extern int ReceiveString(int socket, char *str, int maxLen);
- +
- +
- +#endif /* IPC_H */
- diff -Naurp Mesa-7.8.1/progs/xdemos/Makefile Mesa-7.8.1.patched/progs/xdemos/Makefile
- --- Mesa-7.8.1/progs/xdemos/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/Makefile 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,103 @@
- +# progs/xdemos/Makefile
- +
- +TOP = ../..
- +include $(TOP)/configs/current
- +
- +
- +INCDIR = $(TOP)/include
- +
- +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
- +
- +# Add X11 and pthread libs to satisfy GNU gold.
- +APP_LIB_DEPS += -lX11 -lpthread
- +
- +LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS)
- +
- +PROGS = \
- + corender \
- + glsync \
- + glthreads \
- + glxdemo \
- + glxgears \
- + glxgears_fbconfig \
- + glxgears_pixmap \
- + glxcontexts \
- + glxheads \
- + glxinfo \
- + glxpixmap \
- + glxpbdemo \
- + glxsnoop \
- + glxswapcontrol \
- + manywin \
- + msctest \
- + multictx \
- + offset \
- + omlsync \
- + overlay \
- + pbinfo \
- + pbdemo \
- + sharedtex \
- + sharedtex_mt \
- + texture_from_pixmap \
- + wincopy \
- + xfont \
- + xrotfontdemo
- +
- +# Don't build these by default because of extra library dependencies
- +EXTRA_PROGS = \
- + shape \
- + yuvrect_client \
- + xdemo
- +
- +
- +
- +##### RULES #####
- +
- +.o: $(LIB_DEP)
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
- +
- +.c.o:
- + $(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< -c -o $@
- +
- +
- +##### TARGETS #####
- +
- +default: $(PROGS)
- +
- +$(PROGS): $(PROGS:%=%.o)
- +
- +extra: $(EXTRA_PROGS)
- +
- +
- +clean:
- + -rm -f $(PROGS) $(EXTRA_PROGS)
- + -rm -f *.o *~
- +
- +
- +# special cases
- +pbutil.o: pbutil.h
- +pbinfo.o: pbutil.h
- +pbinfo: pbinfo.o pbutil.o
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@
- +
- +pbdemo.o: pbutil.h
- +pbdemo: pbdemo.o pbutil.o
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@
- +
- +glxgears_fbconfig.o: pbutil.h
- +glxgears_fbconfig: glxgears_fbconfig.o pbutil.o
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@
- +
- +xuserotfont.o: xuserotfont.h
- +xrotfontdemo.o: xuserotfont.h
- +xrotfontdemo: xrotfontdemo.o xuserotfont.o
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@
- +
- +ipc.o: ipc.h
- +corender.o: ipc.h
- +corender: corender.o ipc.o
- + $(APP_CC) $(CFLAGS) $(LDFLAGS) corender.o ipc.o $(LIBS) -o $@
- +
- +yuvrect_client: yuvrect_client.o
- + $(APP_CC) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/manywin.c Mesa-7.8.1.patched/progs/xdemos/manywin.c
- --- Mesa-7.8.1/progs/xdemos/manywin.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/manywin.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,421 @@
- +/*
- + * Create N GLX windows/contexts and render to them in round-robin order.
- + * Also, have the contexts share all texture objects.
- + * Press 'd' to delete a texture, 'u' to unbind it.
- + *
- + * Copyright (C) 2000 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <assert.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <X11/keysym.h>
- +
- +
- +/*
- + * Each display/window/context:
- + */
- +struct head {
- + char DisplayName[1000];
- + Display *Dpy;
- + Window Win;
- + GLXContext Context;
- + float Angle;
- + char Renderer[1000];
- + char Vendor[1000];
- + char Version[1000];
- +};
- +
- +
- +#define MAX_HEADS 200
- +static struct head Heads[MAX_HEADS];
- +static int NumHeads = 0;
- +static GLboolean SwapSeparate = GL_TRUE;
- +static GLuint TexObj = 0;
- +
- +
- +static void
- +Error(const char *display, const char *msg)
- +{
- + fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg);
- + exit(1);
- +}
- +
- +
- +static struct head *
- +AddHead(const char *displayName, const char *name)
- +{
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + XVisualInfo *visinfo;
- + int width = 90, height = 90;
- + int xpos = 0, ypos = 0;
- +
- + if (NumHeads >= MAX_HEADS)
- + return NULL;
- +
- + dpy = XOpenDisplay(displayName);
- + if (!dpy) {
- + Error(displayName, "Unable to open display");
- + return NULL;
- + }
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + visinfo = glXChooseVisual(dpy, scrnum, attrib);
- + if (!visinfo) {
- + Error(displayName, "Unable to find RGB, double-buffered visual");
- + return NULL;
- + }
- +
- + /* window attributes */
- + xpos = (NumHeads % 10) * 100;
- + ypos = (NumHeads / 10) * 100;
- + printf("%d, %d\n", xpos, ypos);
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, root, xpos, ypos, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (!win) {
- + Error(displayName, "Couldn't create window");
- + return NULL;
- + }
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + if (NumHeads == 0) {
- + ctx = glXCreateContext(dpy, visinfo, NULL, True);
- + }
- + else {
- + /* share textures & dlists with 0th context */
- + printf("sharing\n");
- + ctx = glXCreateContext(dpy, visinfo, Heads[0].Context, True);
- + }
- + if (!ctx) {
- + Error(displayName, "Couldn't create GLX context");
- + return NULL;
- + }
- +
- + XMapWindow(dpy, win);
- +
- + if (!glXMakeCurrent(dpy, win, ctx)) {
- + Error(displayName, "glXMakeCurrent failed");
- + printf("glXMakeCurrent failed in Redraw()\n");
- + return NULL;
- + }
- +
- + if (NumHeads == 0) {
- + /* create texture object now */
- + static const GLubyte checker[2][2][4] = {
- + { {255, 255, 255, 255}, { 0, 0, 0, 255} },
- + { { 0, 0, 0, 0}, {255, 255, 255, 255} }
- + };
- + glGenTextures(1, &TexObj);
- + assert(TexObj);
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGB,
- + GL_UNSIGNED_BYTE, checker);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- + }
- + else {
- + /* bind 0th context's texture in this context too */
- + assert(TexObj);
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + }
- + glEnable(GL_TEXTURE_2D);
- +
- + /* save the info for this head */
- + {
- + struct head *h = &Heads[NumHeads];
- + const char * tmp;
- +
- + if (strlen(name) + 1 > sizeof(h->DisplayName)) {
- + Error(displayName, "name string overflow");
- + return NULL;
- + }
- + strcpy(h->DisplayName, name);
- +
- + h->Dpy = dpy;
- + h->Win = win;
- + h->Context = ctx;
- + h->Angle = 0.0;
- +
- + tmp = (char *) glGetString(GL_VERSION);
- + if (strlen(tmp) + 1 > sizeof(h->Version)) {
- + Error(displayName, "GL_VERSION string overflow");
- + return NULL;
- + }
- + strcpy(h->Version, tmp);
- +
- + tmp = (char *) glGetString(GL_VENDOR);
- + if (strlen(tmp) + 1 > sizeof(h->Vendor)) {
- + Error(displayName, "GL_VENDOR string overflow");
- + return NULL;
- + }
- + strcpy(h->Vendor, tmp);
- +
- + tmp = (char *) glGetString(GL_RENDERER);
- + if (strlen(tmp) + 1 > sizeof(h->Renderer)) {
- + Error(displayName, "GL_RENDERER string overflow");
- + return NULL;
- + }
- + strcpy(h->Renderer, tmp);
- +
- + NumHeads++;
- + return &Heads[NumHeads-1];
- + }
- +
- +}
- +
- +
- +static void
- +DestroyHeads(void)
- +{
- + int i;
- + for (i = 0; i < NumHeads; i++) {
- + XDestroyWindow(Heads[i].Dpy, Heads[i].Win);
- + glXDestroyContext(Heads[i].Dpy, Heads[i].Context);
- + XCloseDisplay(Heads[i].Dpy);
- + }
- +}
- +
- +
- +static void
- +Redraw(struct head *h)
- +{
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed");
- + printf("glXMakeCurrent failed in Redraw()\n");
- + return;
- + }
- +
- + h->Angle += 1.0;
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.5, 0.5, 0.5, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + /* draw green triangle */
- + glColor3f(0.0, 1.0, 0.0);
- + glPushMatrix();
- + glRotatef(h->Angle, 0, 0, 1);
- + glBegin(GL_TRIANGLES);
- + glTexCoord2f(0.5, 1.0); glVertex2f(0, 0.8);
- + glTexCoord2f(0.0, 0.0); glVertex2f(-0.8, -0.7);
- + glTexCoord2f(1.0, 0.0); glVertex2f(0.8, -0.7);
- + glEnd();
- + glPopMatrix();
- +
- + if (!SwapSeparate)
- + glXSwapBuffers(h->Dpy, h->Win);
- +}
- +
- +
- +static void
- +Swap(struct head *h)
- +{
- + glXSwapBuffers(h->Dpy, h->Win);
- +}
- +
- +
- +static void
- +Resize(const struct head *h, unsigned int width, unsigned int height)
- +{
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
- + return;
- + }
- + glFlush();
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- +}
- +
- +
- +
- +static void
- +EventLoop(void)
- +{
- + while (1) {
- + int i;
- + for (i = 0; i < NumHeads; i++) {
- + struct head *h = &Heads[i];
- + while (XPending(h->Dpy) > 0) {
- + XEvent event;
- + XNextEvent(h->Dpy, &event);
- + if (event.xany.window == h->Win) {
- + switch (event.type) {
- + case Expose:
- + Redraw(h);
- + if (SwapSeparate)
- + Swap(h);
- + break;
- + case ConfigureNotify:
- + Resize(h, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
- + switch (keySym) {
- + case XK_Escape:
- + return;
- + break;
- + case XK_d:
- + case XK_D:
- + printf("Delete Texture in window %d\n", i);
- + glXMakeCurrent(h->Dpy, h->Win, h->Context);
- + glDeleteTextures(1, &TexObj);
- + break;
- + case XK_u:
- + case XK_U:
- + printf("Unbind Texture in window %d\n", i);
- + glXMakeCurrent(h->Dpy, h->Win, h->Context);
- + glBindTexture(GL_TEXTURE_2D, 0);
- + break;
- + }
- + }
- + break;
- + default:
- + /*no-op*/ ;
- + }
- + }
- + else {
- + printf("window mismatch\n");
- + }
- + }
- + }
- +
- + /* redraw all windows */
- + for (i = 0; i < NumHeads; i++) {
- + Redraw(&Heads[i]);
- + }
- + /* swapbuffers on all windows, if not already done */
- + if (SwapSeparate) {
- + for (i = 0; i < NumHeads; i++) {
- + Swap(&Heads[i]);
- + }
- + }
- + usleep(1);
- + }
- +}
- +
- +
- +
- +static void
- +PrintInfo(const struct head *h)
- +{
- + printf("Name: %s\n", h->DisplayName);
- + printf(" Display: %p\n", (void *) h->Dpy);
- + printf(" Window: 0x%x\n", (int) h->Win);
- + printf(" Context: 0x%lx\n", (long) h->Context);
- + printf(" GL_VERSION: %s\n", h->Version);
- + printf(" GL_VENDOR: %s\n", h->Vendor);
- + printf(" GL_RENDERER: %s\n", h->Renderer);
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + char *dpyName = NULL;
- + int i;
- +
- + if (argc == 1) {
- + printf("manywin: open N simultaneous glx windows\n");
- + printf("Usage:\n");
- + printf(" manywin [-s] numWindows\n");
- + printf("Options:\n");
- + printf(" -s = swap immediately after drawing (see src code)\n");
- + printf("Example:\n");
- + printf(" manywin 10\n");
- + return 0;
- + }
- + else {
- + int n = 3;
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-s") == 0) {
- + SwapSeparate = GL_FALSE;
- + }
- + else if (strcmp(argv[i], "-display") == 0 && i < argc) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else {
- + n = atoi(argv[i]);
- + }
- + }
- + if (n < 1)
- + n = 1;
- + if (n > MAX_HEADS)
- + n = MAX_HEADS;
- +
- + printf("%d windows\n", n);
- + for (i = 0; i < n; i++) {
- + char name[100];
- + struct head *h;
- + sprintf(name, "%d", i);
- + h = AddHead(dpyName, name);
- + if (h) {
- + PrintInfo(h);
- + }
- + }
- + }
- +
- + EventLoop();
- + DestroyHeads();
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/msctest.c Mesa-7.8.1.patched/progs/xdemos/msctest.c
- --- Mesa-7.8.1/progs/xdemos/msctest.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/msctest.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,195 @@
- +/*
- + * Copyright © 2009 Intel Corporation
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice (including the next
- + * paragraph) shall be included in all copies or substantial portions of the
- + * Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- + * IN THE SOFTWARE.
- + *
- + * Authors:
- + * Jesse Barnes <jesse.barnes@intel.com>
- + *
- + */
- +
- +/** @file msctest.c
- + * Simple test for MSC functionality.
- + */
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <GL/gl.h>
- +#include <GL/glu.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +#include <X11/X.h>
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +
- +void (*get_sync_values)(Display *dpy, Window winGL, int64_t *ust, int64_t *msc, int64_t *sbc);
- +void (*wait_sync)(Display *dpy, Window winGL, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
- +
- +static int GLXExtensionSupported(Display *dpy, const char *extension)
- +{
- + const char *extensionsString, *pos;
- +
- + extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
- +
- + pos = strstr(extensionsString, extension);
- +
- + if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
- + (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
- + return 1;
- +
- + return 0;
- +}
- +
- +extern char *optarg;
- +extern int optind, opterr, optopt;
- +static char optstr[] = "v";
- +
- +static void usage(char *name)
- +{
- + printf("usage: %s\n", name);
- + exit(-1);
- +}
- +
- +int main(int argc, char *argv[])
- +{
- + Display *disp;
- + XVisualInfo *pvi;
- + XSetWindowAttributes swa;
- + int attrib[14];
- + Window winGL;
- + GLXContext context;
- + int dummy;
- + Atom wmDelete;
- + int verbose = 0, width = 200, height = 200;
- + int c, i = 1;
- + int64_t ust, msc, sbc;
- +
- + opterr = 0;
- + while ((c = getopt(argc, argv, optstr)) != -1) {
- + switch (c) {
- + case 'v':
- + verbose = 1;
- + break;
- + default:
- + usage(argv[0]);
- + break;
- + }
- + }
- +
- + disp = XOpenDisplay(NULL);
- + if (!disp) {
- + fprintf(stderr, "failed to open display\n");
- + return -1;
- + }
- +
- + if (!glXQueryExtension(disp, &dummy, &dummy)) {
- + fprintf(stderr, "glXQueryExtension failed\n");
- + return -1;
- + }
- +
- + if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) {
- + fprintf(stderr, "GLX_OML_sync_control not supported, exiting\n");
- + return -1;
- + }
- +
- + attrib[0] = GLX_RGBA;
- + attrib[1] = 1;
- + attrib[2] = GLX_RED_SIZE;
- + attrib[3] = 1;
- + attrib[4] = GLX_GREEN_SIZE;
- + attrib[5] = 1;
- + attrib[6] = GLX_BLUE_SIZE;
- + attrib[7] = 1;
- + attrib[8] = GLX_DOUBLEBUFFER;
- + attrib[9] = 1;
- + attrib[10] = None;
- +
- + pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib);
- + if (!pvi) {
- + fprintf(stderr, "failed to choose visual, exiting\n");
- + return -1;
- + }
- +
- + context = glXCreateContext(disp, pvi, None, GL_TRUE);
- + if (!context) {
- + fprintf(stderr, "failed to create glx context\n");
- + return -1;
- + }
- +
- + pvi->screen = DefaultScreen(disp);
- +
- + swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
- + pvi->visual, AllocNone);
- + swa.border_pixel = 0;
- + swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
- + StructureNotifyMask;
- + winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
- + 0, 0,
- + width, height,
- + 0, pvi->depth, InputOutput, pvi->visual,
- + CWBorderPixel | CWColormap | CWEventMask, &swa);
- + if (!winGL) {
- + fprintf(stderr, "window creation failed\n");
- + return -1;
- + }
- + wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
- + XSetWMProtocols(disp, winGL, &wmDelete, 1);
- +
- + XSetStandardProperties(disp, winGL, "msc test", "msc text",
- + None, NULL, 0, NULL);
- +
- + XMapRaised(disp, winGL);
- +
- + glXMakeCurrent(disp, winGL, context);
- +
- + get_sync_values = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
- + wait_sync = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
- +
- + if (!get_sync_values || !wait_sync) {
- + fprintf(stderr, "failed to get sync values function\n");
- + return -1;
- + }
- +
- + while (i++) {
- + get_sync_values(disp, winGL, &ust, &msc, &sbc);
- + fprintf(stderr, "ust: %llu, msc: %llu, sbc: %llu\n", ust, msc,
- + sbc);
- +
- + /* Alternate colors to make tearing obvious */
- + if (i & 1)
- + glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- + else
- + glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
- + glClear(GL_COLOR_BUFFER_BIT);
- + glXSwapBuffers(disp, winGL);
- + wait_sync(disp, winGL, 0, 60, 0, &ust, &msc, &sbc);
- + fprintf(stderr,
- + "wait returned ust: %llu, msc: %llu, sbc: %llu\n",
- + ust, msc, sbc);
- + sleep(1);
- + }
- +
- + XDestroyWindow(disp, winGL);
- + glXDestroyContext(disp, context);
- + XCloseDisplay(disp);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/multictx.c Mesa-7.8.1.patched/progs/xdemos/multictx.c
- --- Mesa-7.8.1/progs/xdemos/multictx.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/multictx.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,585 @@
- +/*
- + * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +/*
- + * Test rendering with two contexts into one window.
- + * Setup different rendering state for each context to check that
- + * context switching is handled properly.
- + *
- + * Brian Paul
- + * 6 Aug 2009
- + */
- +
- +
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include <sys/time.h>
- +#include <unistd.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +
- +
- +
- +#ifndef M_PI
- +#define M_PI 3.14159265
- +#endif
- +
- +
- +/** Event handler results: */
- +#define NOP 0
- +#define EXIT 1
- +#define DRAW 2
- +
- +static GLfloat view_rotx = 0.0, view_roty = 210.0, view_rotz = 0.0;
- +static GLint gear1, gear2;
- +static GLfloat angle = 0.0;
- +
- +static GLboolean animate = GL_TRUE; /* Animation */
- +
- +
- +static double
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
- +}
- +
- +
- +/*
- + *
- + * Draw a gear wheel. You'll probably want to call this function when
- + * building a display list since we do a lot of trig here.
- + *
- + * Input: inner_radius - radius of hole at center
- + * outer_radius - radius at center of teeth
- + * width - width of gear
- + * teeth - number of teeth
- + * tooth_depth - depth of tooth
- + */
- +static void
- +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
- + GLint teeth, GLfloat tooth_depth)
- +{
- + GLint i;
- + GLfloat r0, r1, r2;
- + GLfloat angle, da;
- + GLfloat u, v, len;
- +
- + r0 = inner_radius;
- + r1 = outer_radius - tooth_depth / 2.0;
- + r2 = outer_radius + tooth_depth / 2.0;
- +
- + da = 2.0 * M_PI / teeth / 4.0;
- +
- + glShadeModel(GL_FLAT);
- +
- + glNormal3f(0.0, 0.0, 1.0);
- +
- + /* draw front face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw front sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + }
- + glEnd();
- +
- + glNormal3f(0.0, 0.0, -1.0);
- +
- + /* draw back face */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + if (i < teeth) {
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + }
- + }
- + glEnd();
- +
- + /* draw back sides of teeth */
- + glBegin(GL_QUADS);
- + da = 2.0 * M_PI / teeth / 4.0;
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + }
- + glEnd();
- +
- + /* draw outward faces of teeth */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i < teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- +
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
- + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
- + u = r2 * cos(angle + da) - r1 * cos(angle);
- + v = r2 * sin(angle + da) - r1 * sin(angle);
- + len = sqrt(u * u + v * v);
- + u /= len;
- + v /= len;
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
- + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + width * 0.5);
- + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
- + -width * 0.5);
- + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
- + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
- + glNormal3f(v, -u, 0.0);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + width * 0.5);
- + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
- + -width * 0.5);
- + glNormal3f(cos(angle), sin(angle), 0.0);
- + }
- +
- + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
- + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
- +
- + glEnd();
- +
- + glShadeModel(GL_SMOOTH);
- +
- + /* draw inside radius cylinder */
- + glBegin(GL_QUAD_STRIP);
- + for (i = 0; i <= teeth; i++) {
- + angle = i * 2.0 * M_PI / teeth;
- + glNormal3f(-cos(angle), -sin(angle), 0.0);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
- + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
- + }
- + glEnd();
- +}
- +
- +
- +static void
- +draw(int ctx)
- +{
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(view_rotx, 1.0, 0.0, 0.0);
- + glRotatef(view_roty + angle, 0.0, 1.0, 0.0);
- + glRotatef(view_rotz, 0.0, 0.0, 1.0);
- +
- + if (ctx == 0) {
- + glDisable(GL_CULL_FACE);
- + glPushMatrix();
- + glRotatef(angle, 0.0, 0.0, 1.0);
- + glCallList(gear1);
- + glPopMatrix();
- + /* This should not effect the other context's rendering */
- + glEnable(GL_CULL_FACE);
- + glCullFace(GL_FRONT_AND_BACK);
- + }
- + else {
- + glPushMatrix();
- + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
- + glCallList(gear2);
- + glPopMatrix();
- + }
- +
- + glPopMatrix();
- +
- + /* this flush is important since we'll be switching contexts next */
- + glFlush();
- +}
- +
- +
- +
- +static void
- +draw_frame(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
- +{
- + static double tRot0 = -1.0;
- + double dt, t = current_time();
- +
- + if (tRot0 < 0.0)
- + tRot0 = t;
- + dt = t - tRot0;
- + tRot0 = t;
- +
- + if (animate) {
- + /* advance rotation for next frame */
- + angle += 70.0 * dt; /* 70 degrees per second */
- + if (angle > 3600.0)
- + angle -= 3600.0;
- + }
- +
- + glXMakeCurrent(dpy, (GLXDrawable) win, ctx1);
- + draw(0);
- +
- + glXMakeCurrent(dpy, (GLXDrawable) win, ctx2);
- + draw(1);
- +
- + glXSwapBuffers(dpy, win);
- +}
- +
- +
- +/* new window size or exposure */
- +static void
- +reshape(Display *dpy, Window win,
- + GLXContext ctx1, GLXContext ctx2, int width, int height)
- +{
- + int i;
- +
- + width /= 2;
- +
- + /* loop: left half of window, right half of window */
- + for (i = 0; i < 2; i++) {
- + if (i == 0)
- + glXMakeCurrent(dpy, win, ctx1);
- + else
- + glXMakeCurrent(dpy, win, ctx2);
- +
- + glViewport(width * i, 0, width, height);
- + glScissor(width * i, 0, width, height);
- +
- + {
- + GLfloat h = (GLfloat) height / (GLfloat) width;
- +
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- + }
- +
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -30.0);
- + }
- +}
- +
- +
- +
- +static void
- +init(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
- +{
- + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
- + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
- + static GLfloat green[4] = { 0.0, 0.8, 0.2, 0.5 };
- + /*static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };*/
- +
- + /* first ctx */
- + {
- + static GLuint stipple[32] = {
- + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- +
- + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
- + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
- +
- + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- +
- + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
- + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00
- + };
- +
- + glXMakeCurrent(dpy, win, ctx1);
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + gear1 = glGenLists(1);
- + glNewList(gear1, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
- + gear(1.0, 4.0, 1.0, 20, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- + glEnable(GL_SCISSOR_TEST);
- + glClearColor(0.4, 0.4, 0.4, 1.0);
- +
- + glPolygonStipple((GLubyte *) stipple);
- + glEnable(GL_POLYGON_STIPPLE);
- + }
- +
- + /* second ctx */
- + {
- + glXMakeCurrent(dpy, win, ctx2);
- +
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glEnable(GL_DEPTH_TEST);
- +
- + gear2 = glGenLists(1);
- + glNewList(gear2, GL_COMPILE);
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
- + gear(1.5, 3.0, 1.5, 16, 0.7);
- + glEndList();
- +
- + glEnable(GL_NORMALIZE);
- + glEnable(GL_SCISSOR_TEST);
- + glClearColor(0.6, 0.6, 0.6, 1.0);
- +
- + glEnable(GL_BLEND);
- + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- + }
- +}
- +
- +
- +/**
- + * Create an RGB, double-buffered window.
- + * Return the window and two context handles.
- + */
- +static void
- +make_window_and_contexts( Display *dpy, const char *name,
- + int x, int y, int width, int height,
- + Window *winRet,
- + GLXContext *ctxRet1,
- + GLXContext *ctxRet2)
- +{
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attribs );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, x, y, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + *winRet = win;
- + *ctxRet1 = glXCreateContext( dpy, visinfo, NULL, True );
- + *ctxRet2 = glXCreateContext( dpy, visinfo, NULL, True );
- +
- + if (!*ctxRet1 || !*ctxRet2) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + XFree(visinfo);
- +}
- +
- +
- +/**
- + * Handle one X event.
- + * \return NOP, EXIT or DRAW
- + */
- +static int
- +handle_event(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2,
- + XEvent *event)
- +{
- + (void) dpy;
- + (void) win;
- +
- + switch (event->type) {
- + case Expose:
- + return DRAW;
- + case ConfigureNotify:
- + reshape(dpy, win, ctx1, ctx2,
- + event->xconfigure.width, event->xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event->xkey, 0);
- + if (code == XK_Left) {
- + view_roty += 5.0;
- + }
- + else if (code == XK_Right) {
- + view_roty -= 5.0;
- + }
- + else if (code == XK_Up) {
- + view_rotx += 5.0;
- + }
- + else if (code == XK_Down) {
- + view_rotx -= 5.0;
- + }
- + else {
- + r = XLookupString(&event->xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return EXIT;
- + }
- + else if (buffer[0] == 'a' || buffer[0] == 'A') {
- + animate = !animate;
- + }
- + }
- + return DRAW;
- + }
- + }
- + return NOP;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
- +{
- + while (1) {
- + int op;
- + while (!animate || XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + op = handle_event(dpy, win, ctx1, ctx2, &event);
- + if (op == EXIT)
- + return;
- + else if (op == DRAW)
- + break;
- + }
- +
- + draw_frame(dpy, win, ctx1, ctx2);
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + unsigned int winWidth = 800, winHeight = 400;
- + int x = 0, y = 0;
- + Display *dpy;
- + Window win;
- + GLXContext ctx1, ctx2;
- + char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else {
- + return 1;
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n",
- + dpyName ? dpyName : getenv("DISPLAY"));
- + return -1;
- + }
- +
- + make_window_and_contexts(dpy, "multictx", x, y, winWidth, winHeight,
- + &win, &ctx1, &ctx2);
- + XMapWindow(dpy, win);
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + init(dpy, win, ctx1, ctx2);
- +
- + /* Set initial projection/viewing transformation.
- + * We can't be sure we'll get a ConfigureNotify event when the window
- + * first appears.
- + */
- + reshape(dpy, win, ctx1, ctx2, winWidth, winHeight);
- +
- + event_loop(dpy, win, ctx1, ctx2);
- +
- + glDeleteLists(gear1, 1);
- + glDeleteLists(gear2, 1);
- + glXDestroyContext(dpy, ctx1);
- + glXDestroyContext(dpy, ctx2);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/offset.c Mesa-7.8.1.patched/progs/xdemos/offset.c
- --- Mesa-7.8.1/progs/xdemos/offset.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/offset.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,343 @@
- +/****************************************************************************
- +Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
- +
- + All Rights Reserved
- +
- +Permission to use, copy, modify, and distribute this software and its
- +documentation for any purpose and without fee is hereby granted,
- +provided that the above copyright notice appear in all copies and that
- +both that copyright notice and this permission notice appear in
- +supporting documentation, and that the name of Silicon Graphics not be
- +used in advertising or publicity pertaining to distribution of the
- +software without specific, written prior permission.
- +
- +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- +EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- +PERFORMANCE OF THIS SOFTWARE.
- +
- +****************************************************************************/
- +
- +/*
- + * Derived from code written by Kurt Akeley, November 1992
- + *
- + * Uses PolygonOffset to draw hidden-line images. PolygonOffset
- + * shifts the z values of polygons an amount that is
- + * proportional to their slope in screen z. This keeps
- + * the lines, which are drawn without displacement, from
- + * interacting with their respective polygons, and
- + * thus eliminates line dropouts.
- + *
- + * The left image shows an ordinary antialiased wireframe image.
- + * The center image shows an antialiased hidden-line image without
- + * PolygonOffset.
- + * The right image shows an antialiased hidden-line image using
- + * PolygonOffset to reduce artifacts.
- + *
- + * Drag with a mouse button pressed to rotate the models.
- + * Press the escape key to exit.
- + */
- +
- +/*
- + * Modified for OpenGL 1.1 glPolygonOffset() conventions
- + */
- +
- +
- +#include <GL/glx.h>
- +#include <X11/keysym.h>
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +
- +#undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */
- +
- +
- +#ifndef EXIT_FAILURE
- +# define EXIT_FAILURE 1
- +#endif
- +#ifndef EXIT_SUCCESS
- +# define EXIT_SUCCESS 0
- +#endif
- +
- +#define MAXQUAD 6
- +
- +typedef float Vertex[3];
- +
- +typedef Vertex Quad[4];
- +
- +/* data to define the six faces of a unit cube */
- +Quad quads[MAXQUAD] = {
- + { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
- + { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
- + { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
- + { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
- + { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
- + { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */
- +};
- +
- +#define WIREFRAME 0
- +#define HIDDEN_LINE 1
- +
- +static void error(const char* prog, const char* msg);
- +static void cubes(int mx, int my, int mode);
- +static void fill(Quad quad);
- +static void outline(Quad quad);
- +static void draw_hidden(Quad quad, int mode, int face);
- +static void process_input(Display *dpy, Window win);
- +static int query_extension(char* extName);
- +
- +static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None };
- +
- +static int dimension = 3;
- +
- +static float Scale = 1.0;
- +
- +
- +int main(int argc, char** argv) {
- + Display *dpy;
- + XVisualInfo *vi;
- + XSetWindowAttributes swa;
- + Window win;
- + GLXContext cx;
- + GLint z;
- +
- + dpy = XOpenDisplay(0);
- + if (!dpy) error(argv[0], "can't open display");
- +
- + vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
- + if (!vi) error(argv[0], "no suitable visual");
- +
- + cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
- +
- + swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
- + vi->visual, AllocNone);
- +
- + swa.border_pixel = 0;
- + swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
- + ButtonPressMask | ButtonMotionMask;
- + win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
- + 0, vi->depth, InputOutput, vi->visual,
- + CWBorderPixel|CWColormap|CWEventMask, &swa);
- + XStoreName(dpy, win, "hiddenline");
- + XMapWindow(dpy, win);
- +
- + glXMakeCurrent(dpy, win, cx);
- +
- + /* check for the polygon offset extension */
- +#ifndef GL_VERSION_1_1
- + if (!query_extension("GL_EXT_polygon_offset"))
- + error(argv[0], "polygon_offset extension is not available");
- +#else
- + (void) query_extension;
- +#endif
- +
- + /* set up viewing parameters */
- + glMatrixMode(GL_PROJECTION);
- + glFrustum(-1, 1, -1, 1, 6, 20);
- + glMatrixMode(GL_MODELVIEW);
- + glTranslatef(0, 0, -15);
- +
- + /* set other relevant state information */
- + glEnable(GL_DEPTH_TEST);
- +
- + glGetIntegerv(GL_DEPTH_BITS, &z);
- + printf("GL_DEPTH_BITS = %d\n", z);
- +
- +#ifdef GL_EXT_polygon_offset
- + printf("using 1.0 offset extension\n");
- + glPolygonOffsetEXT( 1.0, 0.00001 );
- +#else
- + printf("using 1.1 offset\n");
- + glPolygonOffset( 1.0, 0.5 );
- +#endif
- +
- + glShadeModel( GL_FLAT );
- + glDisable( GL_DITHER );
- +
- + /* process events until the user presses ESC */
- + while (1) process_input(dpy, win);
- +
- + return 0;
- +}
- +
- +static void
- +draw_scene(int mx, int my) {
- + glClearColor(0.25, 0.25, 0.25, 0);
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- + glTranslatef(-1.7, 0.0, 0.0);
- + cubes(mx, my, WIREFRAME);
- + glPopMatrix();
- +
- + glPushMatrix();
- + cubes(mx, my, HIDDEN_LINE);
- + glPopMatrix();
- +
- + glPushMatrix();
- + glTranslatef(1.7, 0.0, 0.0);
- +#ifdef GL_EXT_polygon_offset
- + glEnable(GL_POLYGON_OFFSET_EXT);
- +#else
- + glEnable(GL_POLYGON_OFFSET_FILL);
- +#endif
- + glScalef(Scale, Scale, Scale);
- + cubes(mx, my, HIDDEN_LINE);
- +#ifdef GL_EXT_polygon_offset
- + glDisable(GL_POLYGON_OFFSET_EXT);
- +#else
- + glDisable(GL_POLYGON_OFFSET_FILL);
- +#endif
- + glPopMatrix();
- +}
- +
- +
- +static void
- +cubes(int mx, int my, int mode) {
- + int x, y, z, i;
- +
- + /* track the mouse */
- + glRotatef(mx / 2.0, 0, 1, 0);
- + glRotatef(my / 2.0, 1, 0, 0);
- +
- + /* draw the lines as hidden polygons */
- + glTranslatef(-0.5, -0.5, -0.5);
- + glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
- + for (z = 0; z < dimension; z++) {
- + for (y = 0; y < dimension; y++) {
- + for (x = 0; x < dimension; x++) {
- + glPushMatrix();
- + glTranslatef(x, y, z);
- + glScalef(0.8, 0.8, 0.8);
- + for (i = 0; i < MAXQUAD; i++)
- + draw_hidden(quads[i], mode, i);
- + glPopMatrix();
- + }
- + }
- + }
- +}
- +
- +static void
- +fill(Quad quad) {
- + /* draw a filled polygon */
- + glBegin(GL_QUADS);
- + glVertex3fv(quad[0]);
- + glVertex3fv(quad[1]);
- + glVertex3fv(quad[2]);
- + glVertex3fv(quad[3]);
- + glEnd();
- +}
- +
- +static void
- +outline(Quad quad) {
- + /* draw an outlined polygon */
- + glBegin(GL_LINE_LOOP);
- + glVertex3fv(quad[0]);
- + glVertex3fv(quad[1]);
- + glVertex3fv(quad[2]);
- + glVertex3fv(quad[3]);
- + glEnd();
- +}
- +
- +static void
- +draw_hidden(Quad quad, int mode, int face) {
- + static const GLfloat colors[3][3] = {
- + {0.5, 0.5, 0.0},
- + {0.8, 0.5, 0.0},
- + {0.0, 0.5, 0.8}
- + };
- + if (mode == HIDDEN_LINE) {
- + glColor3fv(colors[face % 3]);
- + fill(quad);
- + }
- +
- + /* draw the outline using white */
- + glColor3f(1, 1, 1);
- + outline(quad);
- +}
- +
- +static void
- +process_input(Display *dpy, Window win) {
- + XEvent event;
- + static int prevx, prevy;
- + static int deltax = 90, deltay = 40;
- +
- + do {
- + char buf[31];
- + KeySym keysym;
- +
- + XNextEvent(dpy, &event);
- + switch(event.type) {
- + case Expose:
- + break;
- + case ConfigureNotify: {
- + /* this approach preserves a 1:1 viewport aspect ratio */
- + int vX, vY, vW, vH;
- + int eW = event.xconfigure.width, eH = event.xconfigure.height;
- + if (eW >= eH) {
- + vX = 0;
- + vY = (eH - eW) >> 1;
- + vW = vH = eW;
- + } else {
- + vX = (eW - eH) >> 1;
- + vY = 0;
- + vW = vH = eH;
- + }
- + glViewport(vX, vY, vW, vH);
- + }
- + break;
- + case KeyPress:
- + (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
- + switch (keysym) {
- + case 'Z':
- + Scale *= 1.1;
- + break;
- + case 'z':
- + Scale *= 0.9;
- + break;
- + case XK_Escape:
- + exit(EXIT_SUCCESS);
- + default:
- + break;
- + }
- + break;
- + case ButtonPress:
- + prevx = event.xbutton.x;
- + prevy = event.xbutton.y;
- + break;
- + case MotionNotify:
- + deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
- + deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
- + break;
- + default:
- + break;
- + }
- + } while (XPending(dpy));
- +
- + draw_scene(deltax, deltay);
- + glXSwapBuffers(dpy, win);
- +}
- +
- +static void
- +error(const char *prog, const char *msg) {
- + fprintf(stderr, "%s: %s\n", prog, msg);
- + exit(EXIT_FAILURE);
- +}
- +
- +static int
- +query_extension(char* extName) {
- + char *p = (char *) glGetString(GL_EXTENSIONS);
- + char *end = p + strlen(p);
- + while (p < end) {
- + int n = strcspn(p, " ");
- + if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
- + return GL_TRUE;
- + p += (n + 1);
- + }
- + return GL_FALSE;
- +}
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/omlsync.c Mesa-7.8.1.patched/progs/xdemos/omlsync.c
- --- Mesa-7.8.1/progs/xdemos/omlsync.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/omlsync.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,265 @@
- +/*
- + * Copyright © 2007-2010 Intel Corporation
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice (including the next
- + * paragraph) shall be included in all copies or substantial portions of the
- + * Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- + * IN THE SOFTWARE.
- + *
- + * Authors:
- + * Jesse Barnes <jesse.barnes@intel.com>
- + *
- + */
- +
- +/** @file omlsync.c
- + * The program is simple: it paints a window alternating colors (red &
- + * white) either as fast as possible or synchronized to vblank events
- + *
- + * If run normally, the program should display a window that exhibits
- + * significant tearing between red and white colors (e.g. you might get
- + * a "waterfall" effect of red and white horizontal bars).
- + *
- + * If run with the '-s b' option, the program should synchronize the
- + * window color changes with the vertical blank period, resulting in a
- + * window that looks orangish with a high frequency flicker (which may
- + * be invisible). If the window is moved to another screen, this
- + * property should be preserved. If the window spans two screens, it
- + * shouldn't tear on whichever screen most of the window is on; the
- + * portion on the other screen may show some tearing (like the
- + * waterfall effect above).
- + *
- + * Other options include '-w <width>' and '-h <height>' to set the
- + * window size.
- + */
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <GL/gl.h>
- +#include <GL/glu.h>
- +#include <GL/glx.h>
- +#include <GL/glxext.h>
- +#include <X11/X.h>
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +
- +Bool (*glXGetSyncValuesOML)(Display *dpy, GLXDrawable drawable,
- + int64_t *ust, int64_t *msc, int64_t *sbc);
- +Bool (*glXGetMscRateOML)(Display *dpy, GLXDrawable drawable, int32_t *numerator,
- + int32_t *denominator);
- +int64_t (*glXSwapBuffersMscOML)(Display *dpy, GLXDrawable drawable,
- + int64_t target_msc, int64_t divisor,
- + int64_t remainder);
- +Bool (*glXWaitForMscOML)(Display *dpy, GLXDrawable drawable, int64_t target_msc,
- + int64_t divisor, int64_t remainder, int64_t *ust,
- + int64_t *msc, int64_t *sbc);
- +Bool (*glXWaitForSbcOML)(Display *dpy, GLXDrawable drawable, int64_t target_sbc,
- + int64_t *ust, int64_t *msc, int64_t *sbc);
- +int (*glXSwapInterval)(int interval);
- +
- +static int GLXExtensionSupported(Display *dpy, const char *extension)
- +{
- + const char *extensionsString, *pos;
- +
- + extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
- +
- + pos = strstr(extensionsString, extension);
- +
- + if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
- + (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
- + return 1;
- +
- + return 0;
- +}
- +
- +extern char *optarg;
- +extern int optind, opterr, optopt;
- +static char optstr[] = "w:h:vd:r:n:i:";
- +
- +static void usage(char *name)
- +{
- + printf("usage: %s [-w <width>] [-h <height>] ...\n", name);
- + printf("\t-d<divisor> - divisor for OML swap\n");
- + printf("\t-r<remainder> - remainder for OML swap\n");
- + printf("\t-n<interval> - wait interval for OML WaitMSC\n");
- + printf("\t-i<swap interval> - swap at most once every n frames\n");
- + printf("\t-v: verbose (print count)\n");
- + exit(-1);
- +}
- +
- +int main(int argc, char *argv[])
- +{
- + Display *disp;
- + XVisualInfo *pvi;
- + XSetWindowAttributes swa;
- + Window winGL;
- + GLXContext context;
- + int dummy;
- + Atom wmDelete;
- + int64_t ust, msc, sbc;
- + int width = 500, height = 500, verbose = 0, divisor = 0, remainder = 0,
- + wait_interval = 0, swap_interval = 1;
- + int c, i = 1;
- + int ret;
- + int db_attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + XSizeHints sizehints;
- +
- + opterr = 0;
- + while ((c = getopt(argc, argv, optstr)) != -1) {
- + switch (c) {
- + case 'w':
- + width = atoi(optarg);
- + break;
- + case 'h':
- + height = atoi(optarg);
- + break;
- + case 'v':
- + verbose = 1;
- + break;
- + case 'd':
- + divisor = atoi(optarg);
- + break;
- + case 'r':
- + remainder = atoi(optarg);
- + break;
- + case 'n':
- + wait_interval = atoi(optarg);
- + break;
- + case 'i':
- + swap_interval = atoi(optarg);
- + break;
- + default:
- + usage(argv[0]);
- + break;
- + }
- + }
- +
- + disp = XOpenDisplay(NULL);
- + if (!disp) {
- + fprintf(stderr, "failed to open display\n");
- + return -1;
- + }
- +
- + if (!glXQueryExtension(disp, &dummy, &dummy)) {
- + fprintf(stderr, "glXQueryExtension failed\n");
- + return -1;
- + }
- +
- + if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) {
- + fprintf(stderr, "GLX_OML_sync_control not supported\n");
- + return -1;
- + }
- +
- + if (!GLXExtensionSupported(disp, "GLX_MESA_swap_control")) {
- + fprintf(stderr, "GLX_MESA_swap_control not supported\n");
- + return -1;
- + }
- +
- + pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs);
- +
- + if (!pvi) {
- + fprintf(stderr, "failed to choose visual, exiting\n");
- + return -1;
- + }
- +
- + pvi->screen = DefaultScreen(disp);
- +
- + swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
- + pvi->visual, AllocNone);
- + swa.border_pixel = 0;
- + swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
- + StructureNotifyMask;
- + winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
- + 0, 0,
- + width, height,
- + 0, pvi->depth, InputOutput, pvi->visual,
- + CWBorderPixel | CWColormap | CWEventMask, &swa);
- + if (!winGL) {
- + fprintf(stderr, "window creation failed\n");
- + return -1;
- + }
- + wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
- + XSetWMProtocols(disp, winGL, &wmDelete, 1);
- +
- + sizehints.x = 0;
- + sizehints.y = 0;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- +
- + XSetNormalHints(disp, winGL, &sizehints);
- + XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
- + None, NULL, 0, &sizehints);
- +
- + context = glXCreateContext(disp, pvi, NULL, GL_TRUE);
- + if (!context) {
- + fprintf(stderr, "failed to create glx context\n");
- + return -1;
- + }
- +
- + XMapWindow(disp, winGL);
- + ret = glXMakeCurrent(disp, winGL, context);
- + if (!ret) {
- + fprintf(stderr, "failed to make context current: %d\n", ret);
- + }
- +
- + glXGetSyncValuesOML = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
- + glXGetMscRateOML = (void *)glXGetProcAddress((unsigned char *)"glXGetMscRateOML");
- + glXSwapBuffersMscOML = (void *)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML");
- + glXWaitForMscOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
- + glXWaitForSbcOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML");
- + glXSwapInterval = (void *)glXGetProcAddress((unsigned char *)"glXSwapIntervalMESA");
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glXSwapInterval(swap_interval);
- + fprintf(stderr, "set swap interval to %d\n", swap_interval);
- +
- + glXGetSyncValuesOML(disp, winGL, &ust, &msc, &sbc);
- + while (i++) {
- + /* Alternate colors to make tearing obvious */
- + if (i & 1) {
- + glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- + glColor3f(1.0f, 1.0f, 1.0f);
- + } else {
- + glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
- + glColor3f(1.0f, 0.0f, 0.0f);
- + }
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- + glRectf(0, 0, width, height);
- +
- + glXSwapBuffersMscOML(disp, winGL, 0, divisor, remainder);
- +
- + if (wait_interval) {
- + glXWaitForMscOML(disp, winGL, msc + wait_interval,
- + 0, 0, &ust, &msc, &sbc);
- + }
- + }
- +
- + XDestroyWindow(disp, winGL);
- + glXDestroyContext(disp, context);
- + XCloseDisplay(disp);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/opencloseopen.c Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c
- --- Mesa-7.8.1/progs/xdemos/opencloseopen.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,189 @@
- +/*
- + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- + * (C) Copyright IBM Corporation 2003
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +#include <stdlib.h>
- +#include <stdio.h>
- +#include <unistd.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +
- +/** \file opencloseopen.c
- + * Simple test for Mesa bug #508473. Create a window and rendering context.
- + * Draw a single frame. Close the window, destroy the context, and close
- + * the display. Re-open the display, create a new window and context. This
- + * should work, but, at least as of Mesa 5.1, it segfaults. See the bug
- + * report for more details.
- + *
- + * Most of the code here was lifed from various other Mesa xdemos.
- + */
- +
- +static void
- +draw(void)
- +{
- + glViewport(0, 0, 300, 300);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.5, 0.5, 0.5, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + /* draw blue quad */
- + glLoadIdentity();
- + glColor3f(0.3, 0.3, 1.0);
- + glPushMatrix();
- + glRotatef(0, 0, 0, 1);
- + glBegin(GL_POLYGON);
- + glVertex2f(-0.5, -0.25);
- + glVertex2f( 0.5, -0.25);
- + glVertex2f( 0.5, 0.25);
- + glVertex2f(-0.5, 0.25);
- + glEnd();
- + glPopMatrix();}
- +
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( const char * dpyName, const char *name,
- + int x, int y, int width, int height,
- + Display **dpyRet, Window *winRet, GLXContext *ctxRet)
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- + Display *dpy;
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
- + exit(1);
- + }
- +
- + *dpyRet = dpy;
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + XFree(visinfo);
- +
- + *winRet = win;
- + *ctxRet = ctx;
- +}
- +
- +
- +static void
- +destroy_window( Display *dpy, Window win, GLXContext ctx )
- +{
- + glXMakeCurrent(dpy, None, NULL);
- + glXDestroyContext(dpy, ctx);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + char *dpyName = NULL;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + }
- +
- + printf("If this program segfaults, then Mesa bug #508473 is probably "
- + "back.\n");
- + make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, win, ctx);
- +
- + draw();
- + glXSwapBuffers(dpy, win);
- + sleep(2);
- +
- + destroy_window(dpy, win, ctx);
- +
- + make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, win, ctx);
- + destroy_window(dpy, win, ctx);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/overlay.c Mesa-7.8.1.patched/progs/xdemos/overlay.c
- --- Mesa-7.8.1/progs/xdemos/overlay.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/overlay.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,246 @@
- +/*
- + * GLX overlay test/demo.
- + *
- + * Brian Paul
- + * 18 July 2005
- + */
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <X11/keysym.h>
- +#include <assert.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +
- +static int WinWidth = 300, WinHeight = 300;
- +static Window NormalWindow = 0;
- +static Window OverlayWindow = 0;
- +static GLXContext NormalContext = 0;
- +static GLXContext OverlayContext = 0;
- +static GLboolean RGBOverlay = GL_FALSE;
- +static GLfloat Angle = 0.0;
- +
- +
- +static void
- +RedrawNormal(Display *dpy)
- +{
- + glXMakeCurrent(dpy, NormalWindow, NormalContext);
- + glViewport(0, 0, WinWidth, WinHeight);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- + glClearColor(0.5, 0.5, 0.5, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- + glColor3f(1.0, 1.0, 0.0);
- + glPushMatrix();
- + glRotatef(Angle, 0, 0, 1);
- + glRectf(-0.8, -0.8, 0.8, 0.8);
- + glPopMatrix();
- + glXSwapBuffers(dpy, NormalWindow);
- +}
- +
- +
- +static void
- +RedrawOverlay(Display *dpy)
- +{
- + glXMakeCurrent(dpy, OverlayWindow, OverlayContext);
- + glViewport(0, 0, WinWidth, WinHeight);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- + glClear(GL_COLOR_BUFFER_BIT);
- + if (RGBOverlay) {
- + glColor3f(0.0, 1.0, 1.0);
- + }
- + else {
- + glIndexi(2);
- + }
- + glBegin(GL_LINES);
- + glVertex2f(-1, -1);
- + glVertex2f(1, 1);
- + glVertex2f(1, -1);
- + glVertex2f(-1, 1);
- + glEnd();
- + glXSwapBuffers(dpy, OverlayWindow);
- +}
- +
- +
- +static Window
- +MakeWindow(Display *dpy, XVisualInfo *visinfo, Window parent,
- + unsigned int width, unsigned int height)
- +{
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, parent, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + return win;
- +}
- +
- +
- +static void
- +MakeNormalWindow(Display *dpy)
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + Window root;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + visinfo = glXChooseVisual(dpy, scrnum, attrib);
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + NormalWindow = MakeWindow(dpy, visinfo, root, WinWidth, WinHeight);
- + assert(NormalWindow);
- +
- + NormalContext = glXCreateContext(dpy, visinfo, NULL, True);
- + assert(NormalContext);
- +}
- +
- +
- +static void
- +MakeOverlayWindow(Display *dpy)
- +{
- + int rgbAttribs[] = {
- + GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_LEVEL, 1,
- + None
- + };
- + int indexAttribs[] = {
- + /*GLX_RGBA, leave this out */
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_LEVEL, 1,
- + None
- + };
- + int scrnum;
- + Window root;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + visinfo = glXChooseVisual(dpy, scrnum, rgbAttribs);
- + if (visinfo) {
- + printf("Found RGB overlay visual 0x%x\n", (int) visinfo->visualid);
- + RGBOverlay = GL_TRUE;
- + }
- + else {
- + visinfo = glXChooseVisual(dpy, scrnum, indexAttribs);
- + if (visinfo) {
- + printf("Found Color Index overlay visual 0x%x\n",
- + (int) visinfo->visualid);
- + /* XXX setup the colormap entries! */
- + }
- + else {
- + printf("Couldn't get an overlay visual.\n");
- + printf("Your hardware probably doesn't support framebuffer overlay planes.\n");
- + exit(1);
- + }
- + }
- +
- + OverlayWindow = MakeWindow(dpy, visinfo, NormalWindow, WinWidth, WinHeight);
- + assert(OverlayWindow);
- +
- + OverlayContext = glXCreateContext(dpy, visinfo, NULL, True);
- + assert(OverlayContext);
- +}
- +
- +
- +static void
- +EventLoop(Display *dpy)
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent(dpy, &event);
- +
- + switch (event.type) {
- + case Expose:
- + RedrawNormal(dpy);
- + RedrawOverlay(dpy);
- + break;
- + case ConfigureNotify:
- + WinWidth = event.xconfigure.width;
- + WinHeight = event.xconfigure.height;
- + if (event.xconfigure.window == NormalWindow)
- + XResizeWindow(dpy, OverlayWindow, WinWidth, WinHeight);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- + }
- + else if (buffer[0] == ' ') {
- + Angle += 5.0;
- + RedrawNormal(dpy);
- + }
- + }
- + break;
- + default:
- + ; /* nothing */
- + }
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy = XOpenDisplay(NULL);
- +
- + assert(dpy);
- +
- + MakeNormalWindow(dpy);
- + MakeOverlayWindow(dpy);
- +
- + XMapWindow(dpy, NormalWindow);
- + XMapWindow(dpy, OverlayWindow);
- +
- + EventLoop(dpy);
- +
- + glXDestroyContext(dpy, OverlayContext);
- + glXDestroyContext(dpy, NormalContext);
- + XDestroyWindow(dpy, OverlayWindow);
- + XDestroyWindow(dpy, NormalWindow);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/pbdemo.c Mesa-7.8.1.patched/progs/xdemos/pbdemo.c
- --- Mesa-7.8.1/progs/xdemos/pbdemo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/pbdemo.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,493 @@
- +
- +/*
- + * This program demonstrates how to do "off-screen" rendering using
- + * the GLX pixel buffer extension.
- + *
- + * Written by Brian Paul for the "OpenGL and Window System Integration"
- + * course presented at SIGGRAPH '97. Updated on 5 October 2002.
- + *
- + * Usage:
- + * pbuffers width height imgfile
- + * Where:
- + * width is the width, in pixels, of the image to generate.
- + * height is the height, in pixels, of the image to generate.
- + * imgfile is the name of the PPM image file to write.
- + *
- + *
- + * This demo draws 3-D boxes with random orientation. A pbuffer with
- + * a depth (Z) buffer is prefered but if such a pbuffer can't be created
- + * we use a non-depth-buffered config.
- + *
- + * On machines such as the SGI Indigo you may have to reconfigure your
- + * display/X server to enable pbuffers. Look in the /usr/gfx/ucode/MGRAS/vof/
- + * directory for display configurationswith the _pbuf suffix. Use
- + * setmon -x <vof> to configure your X server and display for pbuffers.
- + *
- + * O2 systems seem to support pbuffers well.
- + *
- + * IR systems (at least 1RM systems) don't have single-buffered, RGBA,
- + * Z-buffered pbuffer configs. BUT, they DO have DOUBLE-buffered, RGBA,
- + * Z-buffered pbuffers. Note how we try four different fbconfig attribute
- + * lists below!
- + */
- +
- +
- +#include <assert.h>
- +#include <string.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <X11/Xlib.h>
- +#include "pbutil.h"
- +
- +
- +/* Some ugly global vars */
- +static Display *gDpy = NULL;
- +static int gScreen = 0;
- +static FBCONFIG gFBconfig = 0;
- +static PBUFFER gPBuffer = 0;
- +static int gWidth, gHeight;
- +static GLXContext glCtx;
- +
- +
- +
- +/*
- + * Create the pbuffer and return a GLXPbuffer handle.
- + *
- + * We loop over a list of fbconfigs trying to create
- + * a pixel buffer. We return the first pixel buffer which we successfully
- + * create.
- + */
- +static PBUFFER
- +MakePbuffer( Display *dpy, int screen, int width, int height )
- +{
- +#define NUM_FB_CONFIGS 4
- + const char fbString[NUM_FB_CONFIGS][100] = {
- + "Single Buffered, depth buffer",
- + "Double Buffered, depth buffer",
- + "Single Buffered, no depth buffer",
- + "Double Buffered, no depth buffer"
- + };
- + int fbAttribs[NUM_FB_CONFIGS][100] = {
- + {
- + /* Single buffered, with depth buffer */
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 1,
- + GLX_DOUBLEBUFFER, 0,
- + GLX_STENCIL_SIZE, 0,
- + None
- + },
- + {
- + /* Double buffered, with depth buffer */
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 1,
- + GLX_DOUBLEBUFFER, 1,
- + GLX_STENCIL_SIZE, 0,
- + None
- + },
- + {
- + /* Single buffered, without depth buffer */
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 0,
- + GLX_DOUBLEBUFFER, 0,
- + GLX_STENCIL_SIZE, 0,
- + None
- + },
- + {
- + /* Double buffered, without depth buffer */
- + GLX_RENDER_TYPE, GLX_RGBA_BIT,
- + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DEPTH_SIZE, 0,
- + GLX_DOUBLEBUFFER, 1,
- + GLX_STENCIL_SIZE, 0,
- + None
- + }
- + };
- + Bool largest = True;
- + Bool preserve = False;
- + FBCONFIG *fbConfigs;
- + PBUFFER pBuffer = None;
- + int nConfigs;
- + int i;
- + int attempt;
- +
- + for (attempt=0; attempt<NUM_FB_CONFIGS; attempt++) {
- +
- + /* Get list of possible frame buffer configurations */
- + fbConfigs = ChooseFBConfig(dpy, screen, fbAttribs[attempt], &nConfigs);
- + if (nConfigs==0 || !fbConfigs) {
- + printf("Note: glXChooseFBConfig(%s) failed\n", fbString[attempt]);
- + XFree(fbConfigs);
- + continue;
- + }
- +
- +#if 0 /*DEBUG*/
- + for (i=0;i<nConfigs;i++) {
- + printf("Config %d\n", i);
- + PrintFBConfigInfo(dpy, screen, fbConfigs[i], 0);
- + }
- +#endif
- +
- + /* Create the pbuffer using first fbConfig in the list that works. */
- + for (i=0;i<nConfigs;i++) {
- + pBuffer = CreatePbuffer(dpy, screen, fbConfigs[i], width, height, largest, preserve);
- + if (pBuffer) {
- + gFBconfig = fbConfigs[i];
- + gWidth = width;
- + gHeight = height;
- + break;
- + }
- + }
- +
- + if (pBuffer!=None) {
- + break;
- + }
- + }
- +
- + if (pBuffer) {
- + printf("Using: %s\n", fbString[attempt]);
- + }
- +
- + XFree(fbConfigs);
- +
- + return pBuffer;
- +#undef NUM_FB_CONFIGS
- +}
- +
- +
- +
- +/*
- + * Do all the X / GLX setup stuff.
- + */
- +static int
- +Setup(int width, int height)
- +{
- + int pbSupport;
- + XVisualInfo *visInfo;
- +
- + /* Open the X display */
- + gDpy = XOpenDisplay(NULL);
- + if (!gDpy) {
- + printf("Error: couldn't open default X display.\n");
- + return 0;
- + }
- +
- + /* Get default screen */
- + gScreen = DefaultScreen(gDpy);
- +
- + /* Test that pbuffers are available */
- + pbSupport = QueryPbuffers(gDpy, gScreen);
- + if (pbSupport == 1) {
- + printf("Using GLX 1.3 Pbuffers\n");
- + }
- + else if (pbSupport == 2) {
- + printf("Using SGIX Pbuffers\n");
- + }
- + else {
- + printf("Error: pbuffers not available on this screen\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Create Pbuffer */
- + gPBuffer = MakePbuffer( gDpy, gScreen, width, height );
- + if (gPBuffer==None) {
- + printf("Error: couldn't create pbuffer\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Test drawable queries */
- + {
- + unsigned int v;
- + glXQueryDrawable( gDpy, gPBuffer, GLX_WIDTH, &v);
- + printf("GLX_WIDTH = %u\n", v);
- + glXQueryDrawable( gDpy, gPBuffer, GLX_HEIGHT, &v);
- + printf("GLX_HEIGHT = %u\n", v);
- + glXQueryDrawable( gDpy, gPBuffer, GLX_PRESERVED_CONTENTS, &v);
- + printf("GLX_PRESERVED_CONTENTS = %u\n", v);
- + glXQueryDrawable( gDpy, gPBuffer, GLX_LARGEST_PBUFFER, &v);
- + printf("GLX_LARGEST_PBUFFER = %u\n", v);
- + glXQueryDrawable( gDpy, gPBuffer, GLX_FBCONFIG_ID, &v);
- + printf("GLX_FBCONFIG_ID = %u\n", v);
- + }
- +
- + /* Get corresponding XVisualInfo */
- + visInfo = GetVisualFromFBConfig(gDpy, gScreen, gFBconfig);
- + if (!visInfo) {
- + printf("Error: can't get XVisualInfo from FBconfig\n");
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + /* Create GLX context */
- + glCtx = glXCreateContext(gDpy, visInfo, NULL, True);
- + if (!glCtx) {
- + /* try indirect */
- + glCtx = glXCreateContext(gDpy, visInfo, NULL, False);
- + if (!glCtx) {
- + printf("Error: Couldn't create GLXContext\n");
- + XFree(visInfo);
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- + else {
- + printf("Warning: using indirect GLXContext\n");
- + }
- + }
- +
- + /* Bind context to pbuffer */
- + if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) {
- + printf("Error: glXMakeCurrent failed\n");
- + XFree(visInfo);
- + XCloseDisplay(gDpy);
- + return 0;
- + }
- +
- + return 1; /* Success!! */
- +}
- +
- +
- +
- +/* One-time GL setup */
- +static void
- +InitGL(void)
- +{
- + static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0};
- + glEnable(GL_LIGHTING);
- + glEnable(GL_LIGHT0);
- + glLightfv(GL_LIGHT0, GL_POSITION, pos);
- + glEnable(GL_NORMALIZE);
- + glEnable(GL_DEPTH_TEST);
- + glEnable(GL_CULL_FACE);
- +
- + glViewport(0, 0, gWidth, gHeight);
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
- + glMatrixMode( GL_MODELVIEW );
- + glLoadIdentity();
- + glTranslatef( 0.0, 0.0, -15.0 );
- +}
- +
- +
- +/* Return random float in [0,1] */
- +static float
- +Random(void)
- +{
- + int i = rand();
- + return (float) (i % 1000) / 1000.0;
- +}
- +
- +
- +static void
- +RandomColor(void)
- +{
- + GLfloat c[4];
- + c[0] = Random();
- + c[1] = Random();
- + c[2] = Random();
- + c[3] = 1.0;
- + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);
- +}
- +
- +
- +/* This function borrowed from Mark Kilgard's GLUT */
- +static void
- +drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1,
- + GLfloat z0, GLfloat z1, GLenum type)
- +{
- + static GLfloat n[6][3] =
- + {
- + {-1.0, 0.0, 0.0},
- + {0.0, 1.0, 0.0},
- + {1.0, 0.0, 0.0},
- + {0.0, -1.0, 0.0},
- + {0.0, 0.0, 1.0},
- + {0.0, 0.0, -1.0}
- + };
- + static GLint faces[6][4] =
- + {
- + {0, 1, 2, 3},
- + {3, 2, 6, 7},
- + {7, 6, 5, 4},
- + {4, 5, 1, 0},
- + {5, 6, 2, 1},
- + {7, 4, 0, 3}
- + };
- + GLfloat v[8][3], tmp;
- + GLint i;
- +
- + if (x0 > x1) {
- + tmp = x0;
- + x0 = x1;
- + x1 = tmp;
- + }
- + if (y0 > y1) {
- + tmp = y0;
- + y0 = y1;
- + y1 = tmp;
- + }
- + if (z0 > z1) {
- + tmp = z0;
- + z0 = z1;
- + z1 = tmp;
- + }
- + v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
- + v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
- + v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
- + v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
- + v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
- + v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
- +
- + for (i = 0; i < 6; i++) {
- + glBegin(type);
- + glNormal3fv(&n[i][0]);
- + glVertex3fv(&v[faces[i][0]][0]);
- + glVertex3fv(&v[faces[i][1]][0]);
- + glVertex3fv(&v[faces[i][2]][0]);
- + glVertex3fv(&v[faces[i][3]][0]);
- + glEnd();
- + }
- +}
- +
- +
- +
- +/* Render a scene */
- +static void
- +Render(void)
- +{
- + int NumBoxes = 100;
- + int i;
- +
- + glClearColor(0.2, 0.2, 0.9, 0.0);
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + for (i=0;i<NumBoxes;i++) {
- + float tx = -2.0 + 4.0 * Random();
- + float ty = -2.0 + 4.0 * Random();
- + float tz = 4.0 - 16.0 * Random();
- + float sx = 0.1 + Random() * 0.4;
- + float sy = 0.1 + Random() * 0.4;
- + float sz = 0.1 + Random() * 0.4;
- + float rx = Random();
- + float ry = Random();
- + float rz = Random();
- + float ra = Random() * 360.0;
- + glPushMatrix();
- + glTranslatef(tx, ty, tz);
- + glRotatef(ra, rx, ry, rz);
- + glScalef(sx, sy, sz);
- + RandomColor();
- + drawBox(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, GL_POLYGON);
- + glPopMatrix();
- + }
- +
- + glFinish();
- +}
- +
- +
- +
- +static void
- +WriteFile(const char *filename)
- +{
- + FILE *f;
- + GLubyte *image;
- + int i;
- +
- + image = malloc(gWidth * gHeight * 3 * sizeof(GLubyte));
- + if (!image) {
- + printf("Error: couldn't allocate image buffer\n");
- + return;
- + }
- +
- + glPixelStorei(GL_PACK_ALIGNMENT, 1);
- + glReadPixels(0, 0, gWidth, gHeight, GL_RGB, GL_UNSIGNED_BYTE, image);
- +
- + f = fopen(filename, "w");
- + if (!f) {
- + printf("Couldn't open image file: %s\n", filename);
- + return;
- + }
- + fprintf(f,"P6\n");
- + fprintf(f,"# ppm-file created by %s\n", "trdemo2");
- + fprintf(f,"%i %i\n", gWidth, gHeight);
- + fprintf(f,"255\n");
- + fclose(f);
- + f = fopen(filename, "ab"); /* now append binary data */
- + if (!f) {
- + printf("Couldn't append to image file: %s\n", filename);
- + return;
- + }
- +
- + for (i=0;i<gHeight;i++) {
- + GLubyte *rowPtr;
- + /* Remember, OpenGL images are bottom to top. Have to reverse. */
- + rowPtr = image + (gHeight-1-i) * gWidth*3;
- + fwrite(rowPtr, 1, gWidth*3, f);
- + }
- +
- + fclose(f);
- + free(image);
- +
- + printf("Wrote %d by %d image file: %s\n", gWidth, gHeight, filename);
- +}
- +
- +
- +
- +/*
- + * Print message describing command line parameters.
- + */
- +static void
- +Usage(const char *appName)
- +{
- + printf("Usage:\n");
- + printf(" %s width height imgfile\n", appName);
- + printf("Where imgfile is a ppm file\n");
- +}
- +
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + if (argc!=4) {
- + Usage(argv[0]);
- + }
- + else {
- + int width = atoi(argv[1]);
- + int height = atoi(argv[2]);
- + char *fileName = argv[3];
- + if (width<=0) {
- + printf("Error: width parameter must be at least 1.\n");
- + return 1;
- + }
- + if (height<=0) {
- + printf("Error: height parameter must be at least 1.\n");
- + return 1;
- + }
- + if (!Setup(width, height)) {
- + return 1;
- + }
- + InitGL();
- + Render();
- + WriteFile(fileName);
- + DestroyPbuffer(gDpy, gScreen, gPBuffer);
- + }
- + return 0;
- +}
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/pbinfo.c Mesa-7.8.1.patched/progs/xdemos/pbinfo.c
- --- Mesa-7.8.1/progs/xdemos/pbinfo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/pbinfo.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,107 @@
- +
- +/*
- + * Print list of fbconfigs and test each to see if a pbuffer can be created
- + * for that config.
- + *
- + * Brian Paul
- + * April 1997
- + * Updated on 5 October 2002.
- + */
- +
- +
- +#include <X11/Xlib.h>
- +#include <stdio.h>
- +#include <string.h>
- +#include "pbutil.h"
- +
- +
- +
- +
- +static void
- +PrintConfigs(Display *dpy, int screen, Bool horizFormat)
- +{
- + FBCONFIG *fbConfigs;
- + int nConfigs;
- + int i;
- +
- + fbConfigs = GetAllFBConfigs(dpy, screen, &nConfigs);
- + if (!nConfigs || !fbConfigs) {
- + printf("Error: glxGetFBConfigs failed\n");
- + XFree(fbConfigs);
- + return;
- + }
- +
- + printf("Number of fbconfigs: %d\n", nConfigs);
- +
- + if (horizFormat) {
- + printf(" ID VisualType Depth Lvl RGB CI DB Stereo R G B A");
- + printf(" Z S AR AG AB AA MSbufs MSnum Pbuffer Float\n");
- + }
- +
- + /* Print config info */
- + for (i = 0; i < nConfigs; i++) {
- + PrintFBConfigInfo(dpy, screen, fbConfigs[i], horizFormat);
- + }
- +
- + /* free the list */
- + XFree(fbConfigs);
- +}
- +
- +
- +
- +static void
- +PrintUsage(void)
- +{
- + printf("Options:\n");
- + printf(" -display <display-name> specify X display name\n");
- + printf(" -t print in tabular format\n");
- + printf(" -v print in verbose format\n");
- + printf(" -help print this information\n");
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + int scrn;
- + char *dpyName = NULL;
- + Bool horizFormat = True;
- + int i;
- +
- + for (i=1; i<argc; i++) {
- + if (strcmp(argv[i],"-display")==0) {
- + if (i+1<argc) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + }
- + else if (strcmp(argv[i],"-t")==0) {
- + /* tabular format */
- + horizFormat = True;
- + }
- + else if (strcmp(argv[i],"-v")==0) {
- + /* verbose format */
- + horizFormat = False;
- + }
- + else if (strcmp(argv[i],"-help")==0) {
- + PrintUsage();
- + return 0;
- + }
- + else {
- + printf("Unknown option: %s\n", argv[i]);
- + }
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- +
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
- + return 1;
- + }
- +
- + scrn = DefaultScreen(dpy);
- + PrintConfigs(dpy, scrn, horizFormat);
- + XCloseDisplay(dpy);
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/pbutil.c Mesa-7.8.1.patched/progs/xdemos/pbutil.c
- --- Mesa-7.8.1/progs/xdemos/pbutil.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/pbutil.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,446 @@
- +
- +/*
- + * OpenGL pbuffers utility functions.
- + *
- + * Brian Paul
- + * Original code: April 1997
- + * Updated on 5 October 2002
- + * Updated again on 3 January 2005 to use GLX 1.3 functions in preference
- + * to the GLX_SGIX_fbconfig/pbuffer extensions.
- + */
- +
- +#include <stdio.h>
- +#include <string.h>
- +#include "pbutil.h"
- +
- +
- +/**
- + * Test if we pixel buffers are available for a particular X screen.
- + * Input: dpy - the X display
- + * screen - screen number
- + * Return: 0 = fbconfigs not available.
- + * 1 = fbconfigs are available via GLX 1.3.
- + * 2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig
- + */
- +int
- +QueryFBConfig(Display *dpy, int screen)
- +{
- +#if defined(GLX_VERSION_1_3)
- + {
- + /* GLX 1.3 supports pbuffers */
- + int glxVersionMajor, glxVersionMinor;
- + if (!glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)) {
- + /* GLX not available! */
- + return 0;
- + }
- + if (glxVersionMajor * 100 + glxVersionMinor >= 103) {
- + return 1;
- + }
- + /* fall-through */
- + }
- +#endif
- +
- + /* Try the SGIX extensions */
- + {
- + char *extensions;
- + extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
- + if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) {
- + return 2;
- + }
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * Test if we pixel buffers are available for a particular X screen.
- + * Input: dpy - the X display
- + * screen - screen number
- + * Return: 0 = pixel buffers not available.
- + * 1 = pixel buffers are available via GLX 1.3.
- + * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
- + */
- +int
- +QueryPbuffers(Display *dpy, int screen)
- +{
- + int ret;
- +
- + ret = QueryFBConfig(dpy, screen);
- + if (ret == 2) {
- + char *extensions;
- + extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
- + if (extensions && strstr(extensions, "GLX_SGIX_pbuffer"))
- + return 2;
- + else
- + return 0;
- + }
- + else
- + return ret;
- +}
- +
- +FBCONFIG *
- +ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
- +{
- + int fbcSupport = QueryPbuffers(dpy, screen);
- +#if defined(GLX_VERSION_1_3)
- + if (fbcSupport == 1) {
- + return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
- + }
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (fbcSupport == 2) {
- + return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
- + }
- +#endif
- + return NULL;
- +}
- +
- +
- +FBCONFIG *
- +GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
- +{
- + int fbcSupport = QueryFBConfig(dpy, screen);
- +#if defined(GLX_VERSION_1_3)
- + if (fbcSupport == 1) {
- + return glXGetFBConfigs(dpy, screen, nConfigs);
- + }
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (fbcSupport == 2) {
- + /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
- + * of all available configurations.
- + */
- + return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs);
- + }
- +#endif
- + return NULL;
- +}
- +
- +
- +XVisualInfo *
- +GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
- +{
- + int fbcSupport = QueryFBConfig(dpy, screen);
- +#if defined(GLX_VERSION_1_3)
- + if (fbcSupport == 1) {
- + return glXGetVisualFromFBConfig(dpy, config);
- + }
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (fbcSupport == 2) {
- + return glXGetVisualFromFBConfigSGIX(dpy, config);
- + }
- +#endif
- + return NULL;
- +}
- +
- +
- +/**
- + * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
- + * to query an fbconfig attribute.
- + */
- +static int
- +GetFBConfigAttrib(Display *dpy, int screen,
- +#if defined(GLX_VERSION_1_3)
- + const GLXFBConfig config,
- +#elif defined(GLX_SGIX_fbconfig)
- + const GLXFBConfigSGIX config,
- +#endif
- + int attrib
- + )
- +{
- + int fbcSupport = QueryFBConfig(dpy, screen);
- + int value = 0;
- +
- +#if defined(GLX_VERSION_1_3)
- + if (fbcSupport == 1) {
- + /* ok */
- + if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
- + value = 0;
- + }
- + return value;
- + }
- + /* fall-through */
- +#endif
- +
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (fbcSupport == 2) {
- + if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
- + value = 0;
- + }
- + return value;
- + }
- +#endif
- +
- + return value;
- +}
- +
- +
- +
- +/**
- + * Print parameters for a GLXFBConfig to stdout.
- + * Input: dpy - the X display
- + * screen - the X screen number
- + * fbConfig - the fbconfig handle
- + * horizFormat - if true, print in horizontal format
- + */
- +void
- +PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
- +{
- + PBUFFER pBuffer;
- + int width=2, height=2;
- + int bufferSize, level, doubleBuffer, stereo, auxBuffers;
- + int redSize, greenSize, blueSize, alphaSize;
- + int depthSize, stencilSize;
- + int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
- + int sampleBuffers, samples;
- + int drawableType, renderType, xRenderable, xVisual, id;
- + int maxWidth, maxHeight, maxPixels;
- + int optWidth, optHeight;
- + int floatComponents = 0;
- +
- + /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
- + bufferSize = GetFBConfigAttrib(dpy, screen, config, GLX_BUFFER_SIZE);
- + level = GetFBConfigAttrib(dpy, screen, config, GLX_LEVEL);
- + doubleBuffer = GetFBConfigAttrib(dpy, screen, config, GLX_DOUBLEBUFFER);
- + stereo = GetFBConfigAttrib(dpy, screen, config, GLX_STEREO);
- + auxBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_AUX_BUFFERS);
- + redSize = GetFBConfigAttrib(dpy, screen, config, GLX_RED_SIZE);
- + greenSize = GetFBConfigAttrib(dpy, screen, config, GLX_GREEN_SIZE);
- + blueSize = GetFBConfigAttrib(dpy, screen, config, GLX_BLUE_SIZE);
- + alphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ALPHA_SIZE);
- + depthSize = GetFBConfigAttrib(dpy, screen, config, GLX_DEPTH_SIZE);
- + stencilSize = GetFBConfigAttrib(dpy, screen, config, GLX_STENCIL_SIZE);
- + accumRedSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_RED_SIZE);
- + accumGreenSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_GREEN_SIZE);
- + accumBlueSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_BLUE_SIZE);
- + accumAlphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_ALPHA_SIZE);
- + sampleBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLE_BUFFERS);
- + samples = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLES);
- + drawableType = GetFBConfigAttrib(dpy, screen, config, GLX_DRAWABLE_TYPE);
- + renderType = GetFBConfigAttrib(dpy, screen, config, GLX_RENDER_TYPE);
- + xRenderable = GetFBConfigAttrib(dpy, screen, config, GLX_X_RENDERABLE);
- + xVisual = GetFBConfigAttrib(dpy, screen, config, GLX_X_VISUAL_TYPE);
- + if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
- + xVisual = -1;
- +
- + id = GetFBConfigAttrib(dpy, screen, config, GLX_FBCONFIG_ID);
- + maxWidth = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_WIDTH);
- + maxHeight = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_HEIGHT);
- + maxPixels = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_PIXELS);
- +#if defined(GLX_SGIX_pbuffer)
- + optWidth = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX);
- + optHeight = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX);
- +#else
- + optWidth = optHeight = 0;
- +#endif
- +#if defined(GLX_NV_float_buffer)
- + floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV);
- +#endif
- +
- + /* See if we can create a pbuffer with this config */
- + pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
- +
- + if (horizFormat) {
- + printf("0x%-9x ", id);
- + if (xVisual==GLX_STATIC_GRAY) printf("StaticGray ");
- + else if (xVisual==GLX_GRAY_SCALE) printf("GrayScale ");
- + else if (xVisual==GLX_STATIC_COLOR) printf("StaticColor ");
- + else if (xVisual==GLX_PSEUDO_COLOR) printf("PseudoColor ");
- + else if (xVisual==GLX_TRUE_COLOR) printf("TrueColor ");
- + else if (xVisual==GLX_DIRECT_COLOR) printf("DirectColor ");
- + else printf(" -none- ");
- + printf(" %3d %3d %s %s %s %2s ", bufferSize, level,
- + (renderType & GLX_RGBA_BIT_SGIX) ? "y" : ".",
- + (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : ".",
- + doubleBuffer ? "y" : ".",
- + stereo ? "y" : ".");
- + printf("%2d %2d %2d %2d ", redSize, greenSize, blueSize, alphaSize);
- + printf("%2d %2d ", depthSize, stencilSize);
- + printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize,
- + accumAlphaSize);
- + printf(" %2d %2d", sampleBuffers, samples);
- + printf(" %s %c", pBuffer ? "y" : ".",
- + ".y"[floatComponents]);
- + printf("\n");
- + }
- + else {
- + printf("Id 0x%x\n", id);
- + printf(" Buffer Size: %d\n", bufferSize);
- + printf(" Level: %d\n", level);
- + printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
- + printf(" Stereo: %s\n", stereo ? "yes" : "no");
- + printf(" Aux Buffers: %d\n", auxBuffers);
- + printf(" Red Size: %d\n", redSize);
- + printf(" Green Size: %d\n", greenSize);
- + printf(" Blue Size: %d\n", blueSize);
- + printf(" Alpha Size: %d\n", alphaSize);
- + printf(" Depth Size: %d\n", depthSize);
- + printf(" Stencil Size: %d\n", stencilSize);
- + printf(" Accum Red Size: %d\n", accumRedSize);
- + printf(" Accum Green Size: %d\n", accumGreenSize);
- + printf(" Accum Blue Size: %d\n", accumBlueSize);
- + printf(" Accum Alpha Size: %d\n", accumAlphaSize);
- + printf(" Sample Buffers: %d\n", sampleBuffers);
- + printf(" Samples/Pixel: %d\n", samples);
- + printf(" Drawable Types: ");
- + if (drawableType & GLX_WINDOW_BIT) printf("Window ");
- + if (drawableType & GLX_PIXMAP_BIT) printf("Pixmap ");
- + if (drawableType & GLX_PBUFFER_BIT) printf("PBuffer");
- + printf("\n");
- + printf(" Render Types: ");
- + if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
- + if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
- + printf("\n");
- + printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
- +
- + printf(" Pbuffer: %s\n", pBuffer ? "yes" : "no");
- + printf(" Max Pbuffer width: %d\n", maxWidth);
- + printf(" Max Pbuffer height: %d\n", maxHeight);
- + printf(" Max Pbuffer pixels: %d\n", maxPixels);
- + printf(" Optimum Pbuffer width: %d\n", optWidth);
- + printf(" Optimum Pbuffer height: %d\n", optHeight);
- +
- + printf(" Float Components: %s\n", floatComponents ? "yes" : "no");
- + }
- +
- + if (pBuffer) {
- + DestroyPbuffer(dpy, screen, pBuffer);
- + }
- +}
- +
- +
- +
- +GLXContext
- +CreateContext(Display *dpy, int screen, FBCONFIG config)
- +{
- + int fbcSupport = QueryFBConfig(dpy, screen);
- +#if defined(GLX_VERSION_1_3)
- + if (fbcSupport == 1) {
- + /* GLX 1.3 */
- + GLXContext c;
- + c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True);
- + if (!c) {
- + /* try indirect */
- + c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, False);
- + }
- + return c;
- + }
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (fbcSupport == 2) {
- + GLXContext c;
- + c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);
- + if (!c) {
- + c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, False);
- + }
- + return c;
- + }
- +#endif
- + return 0;
- +}
- +
- +
- +void
- +DestroyContext(Display *dpy, GLXContext ctx)
- +{
- + glXDestroyContext(dpy, ctx);
- +}
- +
- +
- +/* This is only used by CreatePbuffer() */
- +static int XErrorFlag = 0;
- +static int HandleXError(Display *dpy, XErrorEvent *event)
- +{
- + XErrorFlag = 1;
- + return 0;
- +}
- +
- +
- +/**
- + * Create a Pbuffer. Use an X error handler to deal with potential
- + * BadAlloc errors.
- + *
- + * Input: dpy - the X display
- + * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
- + * width, height - size of pixel buffer to request, in pixels.
- + * pbAttribs - list of optional pixel buffer attributes
- + * Return: a Pbuffer or None.
- + */
- +PBUFFER
- +CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
- + int width, int height, Bool largest, Bool preserve)
- +{
- + int (*oldHandler)(Display *, XErrorEvent *);
- + PBUFFER pBuffer = None;
- + int pbSupport = QueryPbuffers(dpy, screen);
- +
- + /* Catch X protocol errors with our own error handler */
- + oldHandler = XSetErrorHandler(HandleXError);
- + XErrorFlag = 0;
- +
- +#if defined(GLX_VERSION_1_3)
- + if (pbSupport == 1) {
- + /* GLX 1.3 */
- + int attribs[100], i = 0;
- + attribs[i++] = GLX_PBUFFER_WIDTH;
- + attribs[i++] = width;
- + attribs[i++] = GLX_PBUFFER_HEIGHT;
- + attribs[i++] = height;
- + attribs[i++] = GLX_PRESERVED_CONTENTS;
- + attribs[i++] = preserve;
- + attribs[i++] = GLX_LARGEST_PBUFFER;
- + attribs[i++] = largest;
- + attribs[i++] = 0;
- + pBuffer = glXCreatePbuffer(dpy, config, attribs);
- + }
- + else
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (pbSupport == 2) {
- + int attribs[100], i = 0;
- + attribs[i++] = GLX_PRESERVED_CONTENTS;
- + attribs[i++] = preserve;
- + attribs[i++] = GLX_LARGEST_PBUFFER;
- + attribs[i++] = largest;
- + attribs[i++] = 0;
- + pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
- + }
- + else
- +#endif
- + {
- + pBuffer = None;
- + }
- +
- + XSync(dpy, False);
- + /* Restore original X error handler */
- + (void) XSetErrorHandler(oldHandler);
- +
- + /* Return pbuffer (may be None) */
- + if (!XErrorFlag && pBuffer != None) {
- + /*printf("config %d worked!\n", i);*/
- + return pBuffer;
- + }
- + else {
- + return None;
- + }
- +}
- +
- +
- +void
- +DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
- +{
- + int pbSupport = QueryPbuffers(dpy, screen);
- +#if defined(GLX_VERSION_1_3)
- + if (pbSupport == 1) {
- + glXDestroyPbuffer(dpy, pbuffer);
- + return;
- + }
- +#endif
- +#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- + if (pbSupport == 2) {
- + glXDestroyGLXPbufferSGIX(dpy, pbuffer);
- + return;
- + }
- +#endif
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/pbutil.h Mesa-7.8.1.patched/progs/xdemos/pbutil.h
- --- Mesa-7.8.1/progs/xdemos/pbutil.h 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/pbutil.h 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,69 @@
- +/*
- + * OpenGL pbuffers utility functions.
- + *
- + * Brian Paul
- + * April 1997
- + */
- +
- +
- +#ifndef PBUTIL_H
- +#define PBUTIL_H
- +
- +
- +#define GLX_GLXEXT_PROTOTYPES
- +#include <GL/glx.h>
- +
- +
- +#if defined(GLX_VERSION_1_3)
- +#define PBUFFER GLXPbuffer
- +#define FBCONFIG GLXFBConfig
- +#elif defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- +#define PBUFFER GLXPbufferSGIX
- +#define FBCONFIG GLXFBConfigSGIX
- +#else
- +#define PBUFFER int
- +#define FBCONFIG int
- +#endif
- +
- +
- +extern int
- +QueryFBConfig(Display *dpy, int screen);
- +
- +extern int
- +QueryPbuffers(Display *dpy, int screen);
- +
- +
- +extern void
- +PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat);
- +
- +
- +extern FBCONFIG *
- +ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs);
- +
- +
- +extern FBCONFIG *
- +GetAllFBConfigs(Display *dpy, int screen, int *nConfigs);
- +
- +
- +extern XVisualInfo *
- +GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config);
- +
- +
- +extern GLXContext
- +CreateContext(Display *dpy, int screen, FBCONFIG config);
- +
- +
- +extern void
- +DestroyContext(Display *dpy, GLXContext ctx);
- +
- +
- +extern PBUFFER
- +CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
- + int width, int height, Bool preserve, Bool largest);
- +
- +
- +extern void
- +DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer);
- +
- +
- +#endif /*PBUTIL_H*/
- diff -Naurp Mesa-7.8.1/progs/xdemos/shape.c Mesa-7.8.1.patched/progs/xdemos/shape.c
- --- Mesa-7.8.1/progs/xdemos/shape.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/shape.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,393 @@
- +
- +/*
- + * Example of using the X "shape" extension with OpenGL: render a spinning
- + * cube inside of a non-rectangular window.
- + *
- + * Press ESC to exit. Press up/down to change window shape.
- + *
- + * To compile add "shape" to the PROGS list in Makefile.
- + *
- + * Brian Paul
- + * June 16, 1997
- + *
- + * This program is in the public domain.
- + */
- +
- +
- +#include <math.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <sys/time.h>
- +#include <time.h>
- +#include <unistd.h>
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +#include <X11/keysym.h>
- +#include <X11/extensions/shape.h>
- +#include <GL/glx.h>
- +
- +#ifndef PI
- +#define PI 3.1415926
- +#endif
- +
- +
- +static int Width=500, Height=500;
- +
- +static float Xangle = 0.0, Yangle = 0.0;
- +static int Sides = 5;
- +static int MinSides = 3;
- +static int MaxSides = 20;
- +
- +
- +/* return current time (in seconds) */
- +static double
- +current_time(void)
- +{
- + struct timeval tv;
- +#ifdef __VMS
- + (void) gettimeofday(&tv, NULL );
- +#else
- + struct timezone tz;
- + (void) gettimeofday(&tv, &tz);
- +#endif
- + return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
- +}
- +
- +
- +/*
- + * Draw the OpenGL stuff and do a SwapBuffers.
- + */
- +static void display(Display *dpy, Window win)
- +{
- + float scale = 1.7;
- +
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glPushMatrix();
- +
- + glScalef(scale, scale, scale);
- + glRotatef(Xangle, 1.0, 0.0, 0.0);
- + glRotatef(Yangle, 0.0, 1.0, 0.0);
- +
- + /*
- + * wireframe box
- + */
- + glColor3f(1.0, 1.0, 1.0);
- + glBegin(GL_LINE_LOOP);
- + glVertex3f(-1.0, -1.0, -1.0);
- + glVertex3f( 1.0, -1.0, -1.0);
- + glVertex3f( 1.0, 1.0, -1.0);
- + glVertex3f(-1.0, 1.0, -1.0);
- + glEnd();
- +
- + glBegin(GL_LINE_LOOP);
- + glVertex3f(-1.0, -1.0, 1.0);
- + glVertex3f( 1.0, -1.0, 1.0);
- + glVertex3f( 1.0, 1.0, 1.0);
- + glVertex3f(-1.0, 1.0, 1.0);
- + glEnd();
- +
- + glBegin(GL_LINES);
- + glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
- + glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, 1.0);
- + glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, 1.0);
- + glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
- + glEnd();
- +
- + /*
- + * Solid box
- + */
- + glPushMatrix();
- + glScalef(0.75, 0.75, 0.75);
- +
- + glColor3f(1, 0, 0);
- + glBegin(GL_POLYGON);
- + glVertex3f(1, -1, -1);
- + glVertex3f(1, 1, -1);
- + glVertex3f(1, 1, 1);
- + glVertex3f(1, -1, 1);
- + glEnd();
- +
- + glColor3f(0, 1, 1);
- + glBegin(GL_POLYGON);
- + glVertex3f(-1, -1, -1);
- + glVertex3f(-1, 1, -1);
- + glVertex3f(-1, 1, 1);
- + glVertex3f(-1, -1, 1);
- + glEnd();
- +
- + glColor3f(0, 1, 0);
- + glBegin(GL_POLYGON);
- + glVertex3f(-1, 1, -1);
- + glVertex3f( 1, 1, -1);
- + glVertex3f( 1, 1, 1);
- + glVertex3f(-1, 1, 1);
- + glEnd();
- +
- + glColor3f(1, 0, 1);
- + glBegin(GL_POLYGON);
- + glVertex3f(-1, -1, -1);
- + glVertex3f( 1, -1, -1);
- + glVertex3f( 1, -1, 1);
- + glVertex3f(-1, -1, 1);
- + glEnd();
- +
- + glColor3f(0, 0, 1);
- + glBegin(GL_POLYGON);
- + glVertex3f(-1, -1, 1);
- + glVertex3f( 1, -1, 1);
- + glVertex3f( 1, 1, 1);
- + glVertex3f(-1, 1, 1);
- + glEnd();
- +
- + glColor3f(1, 1, 0);
- + glBegin(GL_POLYGON);
- + glVertex3f(-1, -1, -1);
- + glVertex3f( 1, -1, -1);
- + glVertex3f( 1, 1, -1);
- + glVertex3f(-1, 1, -1);
- + glEnd();
- + glPopMatrix();
- +
- +
- + glPopMatrix();
- +
- + glXSwapBuffers(dpy, win);
- +}
- +
- +
- +/*
- + * This is called when we have to recompute the window shape bitmask.
- + * We just generate an n-sided regular polygon here but any other shape
- + * would be possible.
- + */
- +static void make_shape_mask(Display *dpy, Window win, int width, int height,
- + int sides)
- +{
- + Pixmap shapeMask;
- + XGCValues xgcv;
- + GC gc;
- +
- + /* allocate 1-bit deep pixmap and a GC */
- + shapeMask = XCreatePixmap(dpy, win, width, height, 1);
- + gc = XCreateGC(dpy, shapeMask, 0, &xgcv);
- +
- + /* clear shapeMask to zeros */
- + XSetForeground(dpy, gc, 0);
- + XFillRectangle(dpy, shapeMask, gc, 0, 0, width, height);
- +
- + /* draw mask */
- + XSetForeground(dpy, gc, 1);
- + {
- + int cx = width / 2;
- + int cy = height / 2;
- + float angle = 0.0;
- + float step = 2.0 * PI / sides;
- + float radius = width / 2;
- + int i;
- + XPoint points[100];
- + for (i=0;i<sides;i++) {
- + int x = cx + radius * sin(angle);
- + int y = cy - radius * cos(angle);
- + points[i].x = x;
- + points[i].y = y;
- + angle += step;
- + }
- + XFillPolygon(dpy, shapeMask, gc, points, sides, Convex, CoordModeOrigin);
- + }
- +
- + /* This is the only SHAPE extension call- simple! */
- + XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shapeMask, ShapeSet);
- +
- + XFreeGC(dpy, gc);
- + XFreePixmap(dpy, shapeMask);
- +}
- +
- +
- +/*
- + * Called when window is resized. Do OpenGL viewport and projection stuff.
- + */
- +static void reshape(int width, int height)
- +{
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0.0, 0.0, -10.0);
- +
- + glEnable(GL_DEPTH_TEST);
- +}
- +
- +
- +/*
- + * Process X events.
- + */
- +static void event_loop(Display *dpy, Window win)
- +{
- + while (1) {
- + XEvent event;
- + if (XPending(dpy)) {
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + display(dpy, event.xexpose.window);
- + break;
- + case ConfigureNotify:
- + Width = event.xconfigure.width;
- + Height = event.xconfigure.height,
- + make_shape_mask(dpy, win, Width, Height, Sides);
- + reshape(Width, Height);
- + break;
- + case KeyPress:
- + {
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
- + switch (keySym) {
- + case XK_Escape:
- + exit(0);
- + break;
- + case XK_Up:
- + Sides++;
- + if (Sides>MaxSides) Sides = MaxSides;
- + make_shape_mask(dpy, win, Width, Height, Sides);
- + break;
- + case XK_Down:
- + Sides--;
- + if (Sides<MinSides) Sides = MinSides;
- + make_shape_mask(dpy, win, Width, Height, Sides);
- + break;
- + }
- + }
- + break;
- + default:
- + ;;
- + }
- + }
- + else {
- + static double t0 = -1.0;
- + double dt, t = current_time();
- + if (t0 < 0.0)
- + t0 = t;
- + dt = t - t0;
- + Xangle += 90.0 * dt; /* 90 degrees per second */
- + Yangle += 70.0 * dt;
- + t0 = t;
- + display(dpy, win);
- + }
- + }
- +}
- +
- +
- +/*
- + * Allocate a "nice" colormap. This could be better (HP-CR support, etc).
- + */
- +static Colormap alloc_colormap(Display *dpy, Window parent, Visual *vis)
- +{
- + Screen *scr = DefaultScreenOfDisplay(dpy);
- + int scrnum = DefaultScreen(dpy);
- +
- + if (MaxCmapsOfScreen(scr)==1 && vis==DefaultVisual(dpy, scrnum)) {
- + /* The window and root are of the same visual type so */
- + /* share the root colormap. */
- + return DefaultColormap(dpy, scrnum);
- + }
- + else {
- + return XCreateColormap(dpy, parent, vis, AllocNone);
- + }
- +}
- +
- +
- +int main(int argc, char *argv[])
- +{
- + static int glAttribs[] = {
- + GLX_DOUBLEBUFFER,
- + GLX_RGBA,
- + GLX_DEPTH_SIZE, 1,
- + None
- + };
- + Display *dpy;
- + XVisualInfo *visInfo;
- + int scrn;
- + Window root;
- + Colormap cmap;
- + Window win;
- + XSetWindowAttributes winAttribs;
- + unsigned long winAttribsMask;
- + GLXContext glCtx;
- + int ignore;
- + const char *name = "OpenGL in a Shaped Window";
- +
- + dpy = XOpenDisplay(NULL);
- + if (!dpy) {
- + fprintf(stderr, "Couldn't open default display\n");
- + return 1;
- + }
- +
- + /* check that we can use the shape extension */
- + if (!XQueryExtension(dpy, "SHAPE", &ignore, &ignore, &ignore )) {
- + fprintf(stderr, "Display doesn't support shape extension\n");
- + return 1;
- + }
- +
- + scrn = DefaultScreen(dpy);
- +
- + root = RootWindow(dpy, scrn);
- +
- + visInfo = glXChooseVisual(dpy, scrn, glAttribs);
- + if (!visInfo) {
- + fprintf(stderr, "Couldn't get RGB, DB, Z visual\n");
- + return 1;
- + }
- +
- + glCtx = glXCreateContext(dpy, visInfo, 0, True);
- + if (!glCtx) {
- + fprintf(stderr, "Couldn't create GL context\n");
- + return 1;
- + }
- +
- + cmap = alloc_colormap(dpy, root, visInfo->visual);
- + if (!cmap) {
- + fprintf(stderr, "Couln't create colormap\n");
- + return 1;
- + }
- +
- + winAttribs.border_pixel = 0;
- + winAttribs.colormap = cmap;
- + winAttribs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + winAttribsMask = CWBorderPixel | CWColormap | CWEventMask;
- + win = XCreateWindow(dpy, root, 0, 0, Width, Height, 0,
- + visInfo->depth, InputOutput,
- + visInfo->visual,
- + winAttribsMask, &winAttribs);
- +
- + {
- + XSizeHints sizehints;
- + /*
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + */
- + sizehints.flags = 0;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + XMapWindow(dpy, win);
- +
- + glXMakeCurrent(dpy, win, glCtx);
- +
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("Press ESC to exit.\n");
- + printf("Press up/down to change window shape.\n");
- +
- + event_loop(dpy, win);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex.c Mesa-7.8.1.patched/progs/xdemos/sharedtex.c
- --- Mesa-7.8.1/progs/xdemos/sharedtex.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/sharedtex.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,324 @@
- +/*
- + * Test sharing of texture objects by two rendering contexts.
- + * In particular, test that changing a texture object in one context
- + * effects the texture in the second context.
- + *
- + * Brian Paul
- + * 30 Apr 2008
- + *
- + * Copyright (C) 2008 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <assert.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <X11/keysym.h>
- +
- +
- +#define MAX_CONTEXTS 2
- +
- +#define TEX_SIZE 32
- +
- +static const char *DisplayName = NULL;
- +static Display *Dpy;
- +static XVisualInfo *VisInfo;
- +static Window Win;
- +static GLXContext Contexts[MAX_CONTEXTS];
- +static int WinWidth = 300, WinHeight = 300;
- +
- +static int DrawContext = 0, TexContext = 1;
- +
- +static GLuint TexObj = 0;
- +static GLboolean NewTexture = GL_FALSE;
- +
- +
- +static void
- +Error(const char *msg)
- +{
- + fprintf(stderr, "sharedtex error: %s\n", msg);
- + exit(1);
- +}
- +
- +
- +static void
- +CreateWindow(const char *name)
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + int xpos = 0, ypos = 0;
- + static int n = 0;
- +
- + scrnum = DefaultScreen(Dpy);
- + root = RootWindow(Dpy, scrnum);
- +
- + VisInfo = glXChooseVisual(Dpy, scrnum, attrib);
- + if (!VisInfo) {
- + Error("Unable to find RGB, double-buffered visual");
- + }
- +
- + /* window attributes */
- + xpos = (n % 10) * 100;
- + ypos = (n / 10) * 100;
- + n++;
- +
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(Dpy, root, VisInfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + Win = XCreateWindow(Dpy, root, xpos, ypos, WinWidth, WinHeight,
- + 0, VisInfo->depth, InputOutput,
- + VisInfo->visual, mask, &attr);
- + if (!Win) {
- + Error("Couldn't create window");
- + }
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = WinWidth;
- + sizehints.height = WinHeight;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(Dpy, Win, &sizehints);
- + XSetStandardProperties(Dpy, Win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + XMapWindow(Dpy, Win);
- +}
- +
- +
- +/**
- + * Change texture image, using TexContext
- + */
- +static void
- +ModifyTexture(void)
- +{
- + GLuint tex[TEX_SIZE][TEX_SIZE];
- + GLuint c0, c1;
- + int i, j;
- +
- + if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) {
- + Error("glXMakeCurrent failed");
- + }
- +
- + /* choose two random colors */
- + c0 = rand() & 0xffffffff;
- + c1 = rand() & 0xffffffff;
- +
- + for (i = 0; i < TEX_SIZE; i++) {
- + for (j = 0; j < TEX_SIZE; j++) {
- + if (((i / 4) ^ (j / 4)) & 1) {
- + tex[i][j] = c0;
- + }
- + else {
- + tex[i][j] = c1;
- + }
- + }
- + }
- +
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
- + GL_RGBA, GL_UNSIGNED_BYTE, tex);
- +
- + NewTexture = GL_TRUE;
- +}
- +
- +
- +static void
- +InitContext(void)
- +{
- + glGenTextures(1, &TexObj);
- + assert(TexObj);
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- + glEnable(GL_TEXTURE_2D);
- +
- + printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER));
- +}
- +
- +
- +static void
- +Setup(void)
- +{
- + int i;
- +
- + Dpy = XOpenDisplay(DisplayName);
- + if (!Dpy) {
- + Error("Unable to open display");
- + }
- +
- + CreateWindow("sharedtex");
- +
- + for (i = 0; i < MAX_CONTEXTS; i++) {
- + GLXContext share = i > 0 ? Contexts[0] : 0;
- +
- + Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True);
- + if (!Contexts[i]) {
- + Error("Unable to create GLX context");
- + }
- +
- + if (!glXMakeCurrent(Dpy, Win, Contexts[i])) {
- + Error("glXMakeCurrent failed");
- + }
- +
- + InitContext();
- + }
- +
- + ModifyTexture();
- +}
- +
- +
- +/**
- + * Redraw window, using DrawContext
- + */
- +static void
- +Redraw(void)
- +{
- + static float rot = 0.0;
- + float ar;
- +
- + rot += 1.0;
- +
- + if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) {
- + Error("glXMakeCurrent failed");
- + }
- +
- + glViewport(0, 0, WinWidth, WinHeight);
- + ar = (float) WinWidth / (float) WinHeight;
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.5, 0.5, 0.5, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + glPushMatrix();
- + glRotatef(rot, 0, 0, 1);
- + glScalef(0.7, 0.7, 0.7);
- +
- + if (NewTexture) {
- + /* rebind to get new contents */
- + glBindTexture(GL_TEXTURE_2D, TexObj);
- + NewTexture = GL_FALSE;
- + }
- +
- + /* draw textured quad */
- + glBegin(GL_POLYGON);
- + glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
- + glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 );
- + glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 );
- + glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 );
- + glEnd();
- +
- + glPopMatrix();
- +
- + if (Win)
- + glXSwapBuffers(Dpy, Win);
- +}
- +
- +
- +static void
- +EventLoop(void)
- +{
- + while (1) {
- + while (XPending(Dpy) > 0) {
- + XEvent event;
- + XNextEvent(Dpy, &event);
- +
- + switch (event.type) {
- + case Expose:
- + Redraw();
- + break;
- + case ConfigureNotify:
- + WinWidth = event.xconfigure.width;
- + WinHeight = event.xconfigure.height;
- + break;
- + case KeyPress:
- + {
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
- + switch (keySym) {
- + case XK_Escape:
- + exit(0);
- + break;
- + case XK_t:
- + case XK_T:
- + ModifyTexture();
- + break;
- + default:
- + ;
- + }
- + }
- + Redraw();
- + break;
- + default:
- + /*no-op*/ ;
- + }
- + }
- +
- + Redraw();
- + usleep(10000);
- + }
- +}
- +
- +
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0 && i < argc) {
- + DisplayName = argv[i+1];
- + i++;
- + }
- + }
- +
- + Setup();
- +
- + printf("Press 't' to change texture image/colors\n");
- +
- + EventLoop();
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex_mt.c Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c
- --- Mesa-7.8.1/progs/xdemos/sharedtex_mt.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,490 @@
- +/* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */
- +
- +/*
- + * Test sharing of display lists and texture objects between GLX contests.
- + * Brian Paul
- + * Summer 2000
- + *
- + *
- + * Copyright (C) 2000 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + *
- + *
- + * Modified 2009 for multithreading by Thomas Hellstrom.
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <unistd.h>
- +#include <string.h>
- +#include <pthread.h>
- +#include <X11/X.h>
- +
- +struct thread_init_arg {
- + int id;
- +};
- +
- +struct window {
- + pthread_mutex_t drawMutex;
- + char DisplayName[1000];
- + Display *Dpy;
- + Window Win;
- + GLXContext Context;
- + float Angle;
- + int Id;
- + XVisualInfo *visInfo;
- +};
- +
- +
- +#define MAX_WINDOWS 20
- +static struct window Windows[MAX_WINDOWS];
- +static int NumWindows = 0;
- +static int terminate = 0;
- +static GLXContext gCtx;
- +static Display *gDpy;
- +static GLuint Textures[3];
- +
- +
- +
- +static void
- +Error(const char *display, const char *msg)
- +{
- + fprintf(stderr, "Error on display %s - %s\n", display, msg);
- + exit(1);
- +}
- +
- +
- +static int
- +initMainthread(Display *dpy, const char *displayName)
- +{
- + int scrnum;
- + XVisualInfo *visinfo;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- +
- + scrnum = DefaultScreen(dpy);
- + visinfo = glXChooseVisual(dpy, scrnum, attrib);
- + if (!visinfo) {
- + Error(displayName, "Unable to find RGB, double-buffered visual");
- + return -1;
- + }
- + gCtx = glXCreateContext(dpy, visinfo, NULL, True);
- + if (!gCtx) {
- + Error(displayName, "Couldn't create GLX context");
- + return -1;
- + }
- + return 0;
- +}
- +
- +static struct window *
- +AddWindow(Display *dpy, const char *displayName, int xpos, int ypos,
- + GLXContext sCtx)
- +{
- + Window win;
- + GLXContext ctx;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + XVisualInfo *visinfo;
- + int width = 300, height = 300;
- +
- + if (NumWindows >= MAX_WINDOWS)
- + return NULL;
- +
- + scrnum = DefaultScreen(dpy);
- + root = RootWindow(dpy, scrnum);
- +
- + visinfo = glXChooseVisual(dpy, scrnum, attrib);
- + if (!visinfo) {
- + Error(displayName, "Unable to find RGB, double-buffered visual");
- + return NULL;
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, root, xpos, ypos, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (!win) {
- + Error(displayName, "Couldn't create window");
- + return NULL;
- + }
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, displayName, displayName,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + ctx = glXCreateContext(dpy, visinfo,
- + sCtx ? sCtx : NULL, True);
- +
- + if (!ctx) {
- + Error(displayName, "Couldn't create GLX context");
- + return NULL;
- + }
- +
- + XMapWindow(dpy, win);
- +
- + /* save the info for this window */
- + {
- + static int id = 0;
- + struct window *h = &Windows[NumWindows];
- + if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
- + Error(displayName, "string overflow");
- + return NULL;
- + }
- + strcpy(h->DisplayName, displayName);
- + h->Dpy = dpy;
- + h->Win = win;
- + h->Context = ctx;
- + h->Angle = 0.0;
- + h->Id = id++;
- + h->visInfo = visinfo;
- + pthread_mutex_init(&h->drawMutex, NULL);
- + NumWindows++;
- + return &Windows[NumWindows-1];
- + }
- +}
- +
- +
- +static void
- +InitGLstuff(void)
- +
- +{
- + glGenTextures(3, Textures);
- +
- + /* setup first texture object */
- + {
- + GLubyte image[16][16][4];
- + GLint i, j;
- + glBindTexture(GL_TEXTURE_2D, Textures[0]);
- +
- + /* red/white checkerboard */
- + for (i = 0; i < 16; i++) {
- + for (j = 0; j < 16; j++) {
- + if ((i ^ j) & 1) {
- + image[i][j][0] = 255;
- + image[i][j][1] = 255;
- + image[i][j][2] = 255;
- + image[i][j][3] = 255;
- + }
- + else {
- + image[i][j][0] = 255;
- + image[i][j][1] = 0;
- + image[i][j][2] = 0;
- + image[i][j][3] = 255;
- + }
- + }
- + }
- +
- + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
- + GL_UNSIGNED_BYTE, image);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- + }
- +
- + /* setup second texture object */
- + {
- + GLubyte image[8][8][3];
- + GLint i, j;
- + glBindTexture(GL_TEXTURE_2D, Textures[1]);
- +
- + /* green/yellow checkerboard */
- + for (i = 0; i < 8; i++) {
- + for (j = 0; j < 8; j++) {
- + if ((i ^ j) & 1) {
- + image[i][j][0] = 0;
- + image[i][j][1] = 255;
- + image[i][j][2] = 0;
- + }
- + else {
- + image[i][j][0] = 255;
- + image[i][j][1] = 255;
- + image[i][j][2] = 0;
- + }
- + }
- + }
- +
- + glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
- + GL_UNSIGNED_BYTE, image);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- + }
- +
- + /* setup second texture object */
- + {
- + GLubyte image[4][4][3];
- + GLint i, j;
- + glBindTexture(GL_TEXTURE_2D, Textures[2]);
- +
- + /* blue/gray checkerboard */
- + for (i = 0; i < 4; i++) {
- + for (j = 0; j < 4; j++) {
- + if ((i ^ j) & 1) {
- + image[i][j][0] = 0;
- + image[i][j][1] = 0;
- + image[i][j][2] = 255;
- + }
- + else {
- + image[i][j][0] = 200;
- + image[i][j][1] = 200;
- + image[i][j][2] = 200;
- + }
- + }
- + }
- +
- + glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
- + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
- + GL_UNSIGNED_BYTE, image);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- + }
- +
- + /* Now make the cube object display list */
- +
- + printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
- +}
- +
- +static void
- +Redraw(struct window *h)
- +{
- + pthread_mutex_lock(&h->drawMutex);
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
- + pthread_mutex_unlock(&h->drawMutex);
- + return;
- + }
- +
- + h->Angle += 1.0;
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.25, 0.25, 0.25, 1.0);
- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- +
- + glEnable(GL_TEXTURE_2D);
- + glEnable(GL_DEPTH_TEST);
- + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- +
- + glColor3f(1, 1, 1);
- +
- + glPushMatrix();
- + if (h->Id == 0)
- + glRotatef(h->Angle, 0, 1, -1);
- + else if (h->Id == 1)
- + glRotatef(-(h->Angle), 0, 1, -1);
- + else if (h->Id == 2)
- + glRotatef(h->Angle, 0, 1, 1);
- + else if (h->Id == 3)
- + glRotatef(-(h->Angle), 0, 1, 1);
- + glBindTexture(GL_TEXTURE_2D, Textures[0]);
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
- + glEnd();
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
- + glEnd();
- +
- + glBindTexture(GL_TEXTURE_2D, Textures[1]);
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
- + glEnd();
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
- + glEnd();
- +
- + glBindTexture(GL_TEXTURE_2D, Textures[2]);
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
- + glEnd();
- + glBegin(GL_POLYGON);
- + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
- + glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
- + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
- + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
- + glEnd();
- +
- + glPopMatrix();
- +
- + glXSwapBuffers(h->Dpy, h->Win);
- +
- + if (!glXMakeCurrent(h->Dpy, None, NULL)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
- + }
- + pthread_mutex_unlock(&h->drawMutex);
- +}
- +
- +static void *threadRunner (void *arg)
- +{
- + struct thread_init_arg *tia = (struct thread_init_arg *) arg;
- + struct window *win;
- +
- + win = &Windows[tia->id];
- +
- + while(!terminate) {
- + usleep(1000);
- + Redraw(win);
- + }
- +
- + return NULL;
- +}
- +
- +static void
- +Resize(struct window *h, unsigned int width, unsigned int height)
- +{
- + pthread_mutex_lock(&h->drawMutex);
- +
- + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
- + pthread_mutex_unlock(&h->drawMutex);
- + return;
- + }
- +
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glFrustum(-1, 1, -1, 1, 2, 10);
- + glMatrixMode(GL_MODELVIEW);
- + glLoadIdentity();
- + glTranslatef(0, 0, -4.5);
- + if (!glXMakeCurrent(h->Dpy, None, NULL)) {
- + Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
- + }
- + pthread_mutex_unlock(&h->drawMutex);
- +}
- +
- +
- +static void
- +EventLoop(void)
- +{
- + while (1) {
- + int i;
- + XEvent event;
- + XNextEvent(gDpy, &event);
- + for (i = 0; i < NumWindows; i++) {
- + struct window *h = &Windows[i];
- + if (event.xany.window == h->Win) {
- + switch (event.type) {
- + case Expose:
- + Redraw(h);
- + break;
- + case ConfigureNotify:
- + Resize(h, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + terminate = 1;
- + return;
- + default:
- + /*no-op*/ ;
- + }
- + }
- + }
- + }
- +}
- +
- +int
- +main(int argc, char *argv[])
- +{
- + const char *dpyName = XDisplayName(NULL);
- + pthread_t t0, t1, t2, t3;
- + struct thread_init_arg tia0, tia1, tia2, tia3;
- + struct window *h0;
- +
- + XInitThreads();
- +
- + gDpy = XOpenDisplay(dpyName);
- + if (!gDpy) {
- + Error(dpyName, "Unable to open display");
- + return -1;
- + }
- +
- + if (initMainthread(gDpy, dpyName))
- + return -1;
- +
- + /* four windows and contexts sharing display lists and texture objects */
- + h0 = AddWindow(gDpy, dpyName, 10, 10, gCtx);
- + (void) AddWindow(gDpy, dpyName, 330, 10, gCtx);
- + (void) AddWindow(gDpy, dpyName, 10, 350, gCtx);
- + (void) AddWindow(gDpy, dpyName, 330, 350, gCtx);
- +
- + if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) {
- + Error(dpyName, "glXMakeCurrent failed for init thread.");
- + return -1;
- + }
- +
- + InitGLstuff();
- +
- + tia0.id = 0;
- + pthread_create(&t0, NULL, threadRunner, &tia0);
- + tia1.id = 1;
- + pthread_create(&t1, NULL, threadRunner, &tia1);
- + tia2.id = 2;
- + pthread_create(&t2, NULL, threadRunner, &tia2);
- + tia3.id = 3;
- + pthread_create(&t3, NULL, threadRunner, &tia3);
- + EventLoop();
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c
- --- Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,396 @@
- +/*
- + * Mesa 3-D graphics library
- + * Version: 7.1
- + *
- + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * Test the GLX_EXT_texture_from_pixmap extension
- + * Brian Paul
- + * 19 May 2007
- + */
- +
- +
- +#define GL_GLEXT_PROTOTYPES
- +#define GLX_GLXEXT_PROTOTYPES
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <X11/keysym.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +
- +
- +static float top, bottom;
- +
- +static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL;
- +static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL;
- +
- +
- +static Display *
- +OpenDisplay(void)
- +{
- + int screen;
- + Display *dpy;
- + const char *ext;
- +
- + dpy = XOpenDisplay(NULL);
- + if (!dpy) {
- + printf("Couldn't open default display!\n");
- + exit(1);
- + }
- +
- + screen = DefaultScreen(dpy);
- + ext = glXQueryExtensionsString(dpy, screen);
- + if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) {
- + fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n");
- + exit(1);
- + }
- +
- + glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC)
- + glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
- + glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC)
- + glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT");
- +
- + if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) {
- + fprintf(stderr, "glXGetProcAddress failed!\n");
- + exit(1);
- + }
- +
- + return dpy;
- +}
- +
- +
- +static GLXFBConfig
- +ChoosePixmapFBConfig(Display *display)
- +{
- + int screen = DefaultScreen(display);
- + GLXFBConfig *fbconfigs;
- + int i, nfbconfigs = 0, value;
- +
- + fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs);
- + for (i = 0; i < nfbconfigs; i++) {
- +
- + glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
- + if (!(value & GLX_PIXMAP_BIT))
- + continue;
- +
- + glXGetFBConfigAttrib(display, fbconfigs[i],
- + GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
- + if (!(value & GLX_TEXTURE_2D_BIT_EXT))
- + continue;
- +
- + glXGetFBConfigAttrib(display, fbconfigs[i],
- + GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
- + if (value == False) {
- + glXGetFBConfigAttrib(display, fbconfigs[i],
- + GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
- + if (value == False)
- + continue;
- + }
- +
- + glXGetFBConfigAttrib(display, fbconfigs[i],
- + GLX_Y_INVERTED_EXT, &value);
- + if (value == True) {
- + top = 0.0f;
- + bottom = 1.0f;
- + }
- + else {
- + top = 1.0f;
- + bottom = 0.0f;
- + }
- +
- + break;
- + }
- +
- + if (i == nfbconfigs) {
- + printf("Unable to find FBconfig for texturing\n");
- + exit(1);
- + }
- +
- + return fbconfigs[i];
- +}
- +
- +
- +static GLXPixmap
- +CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p)
- +{
- + GLXPixmap gp;
- + const int pixmapAttribs[] = {
- + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
- + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
- + None
- + };
- + Window root = RootWindow(dpy, 0);
- +
- + *p = XCreatePixmap(dpy, root, w, h, 24);
- + XSync(dpy, 0);
- + gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs);
- + XSync(dpy, 0);
- +
- + return gp;
- +}
- +
- +
- +static void
- +DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h)
- +{
- + XGCValues gcvals;
- + GC gc;
- +
- + gcvals.background = 0;
- + gc = XCreateGC(dpy, pm, GCBackground, &gcvals);
- +
- + XSetForeground(dpy, gc, 0x0);
- + XFillRectangle(dpy, pm, gc, 0, 0, w, h);
- +
- + XSetForeground(dpy, gc, 0xff0000);
- + XFillRectangle(dpy, pm, gc, 0, 0, 50, 50);
- +
- + XSetForeground(dpy, gc, 0x00ff00);
- + XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50);
- +
- + XSetForeground(dpy, gc, 0x0000ff);
- + XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50);
- +
- + XSetForeground(dpy, gc, 0xffffff);
- + XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50);
- +
- + XSetForeground(dpy, gc, 0xffff00);
- + XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
- + XDrawLine(dpy, pm, gc, 0, 0, w, h);
- + XDrawLine(dpy, pm, gc, 0, h, w, 0);
- +
- + XFreeGC(dpy, gc);
- +}
- +
- +
- +static XVisualInfo *
- +ChooseWindowVisual(Display *dpy)
- +{
- + int screen = DefaultScreen(dpy);
- + XVisualInfo *visinfo;
- + int attribs[] = {
- + GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None
- + };
- +
- + visinfo = glXChooseVisual(dpy, screen, attribs);
- + if (!visinfo) {
- + printf("Unable to find RGB, double-buffered visual\n");
- + exit(1);
- + }
- +
- + return visinfo;
- +}
- +
- +
- +static Window
- +CreateWindow(Display *dpy, XVisualInfo *visinfo,
- + int width, int height, const char *name)
- +{
- + int screen = DefaultScreen(dpy);
- + Window win;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- +
- + root = RootWindow(dpy, screen);
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (win) {
- + XSizeHints sizehints;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- +
- + XMapWindow(dpy, win);
- + }
- + return win;
- +}
- +
- +
- +static void
- +BindPixmapTexture(Display *dpy, GLXPixmap gp)
- +{
- + GLuint texture;
- +
- + glGenTextures(1, &texture);
- + glBindTexture(GL_TEXTURE_2D, texture);
- +
- + glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL);
- +
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- +
- + glEnable(GL_TEXTURE_2D);
- + /*
- + glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT);
- + */
- +}
- +
- +
- +static void
- +Resize(Window win, unsigned int width, unsigned int height)
- +{
- + float sz = 1.5;
- + glViewport(0, 0, width, height);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-sz, sz, -sz, sz, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- +}
- +
- +
- +static void
- +Redraw(Display *dpy, Window win, float rot)
- +{
- + glClearColor(0.25, 0.25, 0.25, 0.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- + glPushMatrix();
- + glRotatef(rot, 0, 0, 1);
- + glRotatef(2.0 * rot, 1, 0, 0);
- +
- + glBegin(GL_QUADS);
- + glTexCoord2d(0.0, bottom);
- + glVertex2f(-1, -1);
- + glTexCoord2d(1.0, bottom);
- + glVertex2f( 1, -1);
- + glTexCoord2d(1.0, top);
- + glVertex2d(1.0, 1.0);
- + glTexCoord2d(0.0, top);
- + glVertex2f(-1.0, 1.0);
- + glEnd();
- +
- + glPopMatrix();
- +
- + glXSwapBuffers(dpy, win);
- +}
- +
- +
- +static void
- +EventLoop(Display *dpy, Window win)
- +{
- + GLfloat rot = 0.0;
- + int anim = 0;
- +
- + while (1) {
- + if (!anim || XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- +
- + switch (event.type) {
- + case Expose:
- + Redraw(dpy, win, rot);
- + break;
- + case ConfigureNotify:
- + Resize(event.xany.window,
- + event.xconfigure.width,
- + event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
- + if (keySym == XK_Escape) {
- + return; /* exit */
- + }
- + else if (keySym == XK_r) {
- + rot += 1.0;
- + Redraw(dpy, win, rot);
- + }
- + else if (keySym == XK_a) {
- + anim = !anim;
- + }
- + else if (keySym == XK_R) {
- + rot -= 1.0;
- + Redraw(dpy, win, rot);
- + }
- + }
- + break;
- + default:
- + ; /*no-op*/
- + }
- + }
- + else {
- + /* animate */
- + rot += 1.0;
- + Redraw(dpy, win, rot);
- + }
- + }
- +}
- +
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + GLXFBConfig pixmapConfig;
- + XVisualInfo *windowVis;
- + GLXPixmap gp;
- + Window win;
- + GLXContext ctx;
- + Pixmap p;
- +
- + dpy = OpenDisplay();
- +
- + pixmapConfig = ChoosePixmapFBConfig(dpy);
- + windowVis = ChooseWindowVisual(dpy);
- + win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap");
- +
- + gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p);
- + DrawPixmapImage(dpy, p, 512, 512);
- +
- + ctx = glXCreateContext(dpy, windowVis, NULL, True);
- + if (!ctx) {
- + printf("Couldn't create GLX context\n");
- + exit(1);
- + }
- +
- + glXMakeCurrent(dpy, win, ctx);
- +
- + BindPixmapTexture(dpy, gp);
- +
- + EventLoop(dpy, win);
- +
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/wincopy.c Mesa-7.8.1.patched/progs/xdemos/wincopy.c
- --- Mesa-7.8.1/progs/xdemos/wincopy.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/wincopy.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,328 @@
- +/*
- + * Mesa 3-D graphics library
- + * Version: 6.5.2
- + *
- + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * This program opens two GLX windows, renders into one and uses
- + * glCopyPixels to copy the image from the first window into the
- + * second by means of the GLX 1.3 function glxMakeContextCurrent().
- + * This function works just like the glXMakeCurrentReadSGI() function
- + * in the GLX_SGI_make_current_read extension.
- + */
- +
- +
- +#define GL_GLEXT_PROTOTYPES
- +#define GLX_GLXEXT_PROTOTYPES
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <X11/keysym.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +
- +
- +#ifdef GLX_VERSION_1_3
- +
- +
- +static Display *Dpy;
- +static int ScrNum;
- +static GLXContext Context;
- +static Window Win[2]; /* Win[0] = source, Win[1] = dest */
- +static GLint Width[2], Height[2];
- +static GLboolean TestClipping = GL_FALSE;
- +static GLfloat Angle = 0.0;
- +
- +static GLboolean DrawFront = GL_FALSE;
- +
- +PFNGLXMAKECURRENTREADSGIPROC make_context_current = NULL;
- +
- +static Window
- +CreateWindow(Display *dpy, int scrnum, XVisualInfo *visinfo,
- + int xpos, int ypos, int width, int height,
- + const char *name)
- +{
- + Window win;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- +
- + root = RootWindow(dpy, scrnum);
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow(dpy, root, xpos, ypos, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr);
- + if (win) {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- +
- + XMapWindow(dpy, win);
- + }
- + return win;
- +}
- +
- +
- +static void
- +Redraw(void)
- +{
- + /* make the first window the current one */
- + if (! (*make_context_current)(Dpy, Win[0], Win[0], Context)) {
- + printf("glXMakeContextCurrent failed in Redraw()\n");
- + return;
- + }
- +
- + Angle += 1.0;
- +
- + if (DrawFront) {
- + glDrawBuffer(GL_FRONT);
- + glReadBuffer(GL_FRONT);
- + }
- + else {
- + glDrawBuffer(GL_BACK);
- + glReadBuffer(GL_BACK);
- + }
- +
- + glViewport(0, 0, Width[0], Height[0]);
- + glMatrixMode(GL_PROJECTION);
- + glLoadIdentity();
- + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- + glMatrixMode(GL_MODELVIEW);
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.5, 0.5, 0.5, 0.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + /* draw blue quad */
- + glColor3f(0.3, 0.3, 1.0);
- + glPushMatrix();
- + glRotatef(Angle, 0, 0, 1);
- + glBegin(GL_POLYGON);
- + glVertex2f(-0.5, -0.25);
- + glVertex2f( 0.5, -0.25);
- + glVertex2f( 0.5, 0.25);
- + glVertex2f(-0.5, 0.25);
- + glEnd();
- + glPopMatrix();
- +
- + if (DrawFront)
- + glFinish();
- + else
- + glXSwapBuffers(Dpy, Win[0]);
- +
- +
- + /* copy image from window 0 to window 1 */
- + if (!(*make_context_current)(Dpy, Win[1], Win[0], Context)) {
- + printf("glXMakeContextCurrent failed in Redraw()\n");
- + return;
- + }
- +
- + /* copy the image between windows */
- + glClearColor(0.0, 0.0, 0.0, 0.0);
- + glClear(GL_COLOR_BUFFER_BIT);
- +
- + if (TestClipping) {
- + glWindowPos2iARB(-2, -2);
- + glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR);
- + }
- + else {
- + glWindowPos2iARB(0, 0);
- + glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR);
- + }
- +
- + if (DrawFront)
- + glFinish();
- + else
- + glXSwapBuffers(Dpy, Win[1]);
- +}
- +
- +
- +
- +static void
- +Resize(Window win, unsigned int width, unsigned int height)
- +{
- + int i;
- + if (win == Win[0]) {
- + i = 0;
- + }
- + else {
- + i = 1;
- + }
- + Width[i] = width;
- + Height[i] = height;
- + if (!glXMakeCurrent(Dpy, Win[i], Context)) {
- + printf("glXMakeCurrent failed in Resize()\n");
- + return;
- + }
- +}
- +
- +
- +
- +static void
- +EventLoop(void)
- +{
- + XEvent event;
- + while (1) {
- + if (XPending(Dpy) > 0) {
- + XNextEvent( Dpy, &event );
- + switch (event.type) {
- + case Expose:
- + Redraw();
- + break;
- + case ConfigureNotify:
- + Resize(event.xany.window, event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buf[100];
- + KeySym keySym;
- + XComposeStatus stat;
- + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
- + if (keySym == XK_Escape) {
- + /* exit */
- + return;
- + }
- + else if (buf[0] == 'f') {
- + DrawFront = !DrawFront;
- + printf("Drawing to %s buffer\n",
- + DrawFront ? "GL_FRONT" : "GL_BACK");
- + }
- + }
- + break;
- + default:
- + /*no-op*/ ;
- + }
- + }
- + else {
- + /* animate */
- + Redraw();
- + }
- + }
- +}
- +
- +
- +static void
- +Init(void)
- +{
- + XVisualInfo *visinfo;
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int major, minor;
- +
- + Dpy = XOpenDisplay(NULL);
- + if (!Dpy) {
- + printf("Couldn't open default display!\n");
- + exit(1);
- + }
- +
- + ScrNum = DefaultScreen(Dpy);
- +
- + glXQueryVersion(Dpy, &major, &minor);
- +
- + if (major * 100 + minor >= 103) {
- + make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
- + glXGetProcAddressARB( (GLubyte *) "glXMakeContextCurrent" );
- + }
- + else {
- + const char * const glxExtensions = glXQueryExtensionsString(Dpy, ScrNum);
- + const char * ext = strstr( glxExtensions, "GLX_SGI_make_current_read" );
- + const size_t len = strlen( "GLX_SGI_make_current_read" );
- +
- + if ( (ext != NULL)
- + && ((ext[len] == ' ') || (ext[len] == '\0')) ) {
- + make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
- + glXGetProcAddressARB( (GLubyte *) "glXMakeCurrentReadSGI" );
- + }
- + }
- +
- + if (make_context_current == NULL) {
- + fprintf(stderr, "Sorry, this program requires either GLX 1.3 "
- + "or GLX_SGI_make_current_read.\n");
- + exit(1);
- + }
- +
- + visinfo = glXChooseVisual(Dpy, ScrNum, attrib);
- + if (!visinfo) {
- + printf("Unable to find RGB, double-buffered visual\n");
- + exit(1);
- + }
- +
- + Context = glXCreateContext(Dpy, visinfo, NULL, True);
- + if (!Context) {
- + printf("Couldn't create GLX context\n");
- + exit(1);
- + }
- +
- +
- + Win[0] = CreateWindow(Dpy, ScrNum, visinfo,
- + 0, 0, 300, 300, "source window");
- +
- + Win[1] = CreateWindow(Dpy, ScrNum, visinfo,
- + 350, 0, 300, 300, "dest window");
- +
- + printf("Press Esc to exit\n");
- + printf("Press 'f' to toggle front/back buffer drawing\n");
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + if (argc > 1 && strcmp(argv[1], "-clip") == 0)
- + TestClipping = GL_TRUE;
- + Init();
- + EventLoop();
- + return 0;
- +}
- +
- +
- +#else
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + printf("This program requires GLX 1.3!\n");
- + return 0;
- +}
- +
- +
- +#endif /* GLX_VERSION_1_3 */
- diff -Naurp Mesa-7.8.1/progs/xdemos/xdemo.c Mesa-7.8.1.patched/progs/xdemos/xdemo.c
- --- Mesa-7.8.1/progs/xdemos/xdemo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/xdemo.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,334 @@
- +
- +/*
- + * Very simple demo of how to use the Mesa/X11 interface instead of the
- + * glx, tk or aux toolkits. I highly recommend using the GLX interface
- + * instead of the X/Mesa interface, however.
- + *
- + * This program is in the public domain.
- + *
- + * Brian Paul
- + */
- +
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +#include "GL/xmesa.h"
- +#include "GL/gl.h"
- +
- +
- +
- +static GLint Black, Red, Green, Blue;
- +
- +
- +
- +static void make_window( char *title, int color_flag )
- +{
- + int x = 10, y = 10, width = 400, height = 300;
- + Display *dpy;
- + int scr;
- + Window root, win;
- + Colormap cmap;
- + XColor xcolor;
- + int attr_flags;
- + XVisualInfo *visinfo;
- + XSetWindowAttributes attr;
- + XTextProperty tp;
- + XSizeHints sh;
- + XEvent e;
- + XMesaContext context;
- + XMesaVisual visual;
- + XMesaBuffer buffer;
- +
- +
- + /*
- + * Do the usual X things to make a window.
- + */
- +
- + dpy = XOpenDisplay(NULL);
- + if (!dpy) {
- + printf("Couldn't open default display!\n");
- + exit(1);
- + }
- +
- + scr = DefaultScreen(dpy);
- + root = RootWindow(dpy, scr);
- +
- + /* alloc visinfo struct */
- + visinfo = (XVisualInfo *) malloc( sizeof(XVisualInfo) );
- +
- + /* Get a visual and colormap */
- + if (color_flag) {
- + /* Open TrueColor window */
- +
- +/*
- + if (!XMatchVisualInfo( dpy, scr, 24, TrueColor, visinfo )) {
- + printf("Couldn't get 24-bit TrueColor visual!\n");
- + exit(1);
- + }
- +*/
- + if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) {
- + printf("Couldn't get 8-bit PseudoColor visual!\n");
- + exit(1);
- + }
- +
- + cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone );
- + Black = Red = Green = Blue = 0;
- + }
- + else {
- + /* Open color index window */
- +
- + if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) {
- + printf("Couldn't get 8-bit PseudoColor visual\n");
- + exit(1);
- + }
- +
- + cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone );
- +
- + /* Allocate colors */
- + xcolor.red = 0x0;
- + xcolor.green = 0x0;
- + xcolor.blue = 0x0;
- + xcolor.flags = DoRed | DoGreen | DoBlue;
- + if (!XAllocColor( dpy, cmap, &xcolor )) {
- + printf("Couldn't allocate black!\n");
- + exit(1);
- + }
- + Black = xcolor.pixel;
- +
- + xcolor.red = 0xffff;
- + xcolor.green = 0x0;
- + xcolor.blue = 0x0;
- + xcolor.flags = DoRed | DoGreen | DoBlue;
- + if (!XAllocColor( dpy, cmap, &xcolor )) {
- + printf("Couldn't allocate red!\n");
- + exit(1);
- + }
- + Red = xcolor.pixel;
- +
- + xcolor.red = 0x0;
- + xcolor.green = 0xffff;
- + xcolor.blue = 0x0;
- + xcolor.flags = DoRed | DoGreen | DoBlue;
- + if (!XAllocColor( dpy, cmap, &xcolor )) {
- + printf("Couldn't allocate green!\n");
- + exit(1);
- + }
- + Green = xcolor.pixel;
- +
- + xcolor.red = 0x0;
- + xcolor.green = 0x0;
- + xcolor.blue = 0xffff;
- + xcolor.flags = DoRed | DoGreen | DoBlue;
- + if (!XAllocColor( dpy, cmap, &xcolor )) {
- + printf("Couldn't allocate blue!\n");
- + exit(1);
- + }
- + Blue = xcolor.pixel;
- + }
- +
- + /* set window attributes */
- + attr.colormap = cmap;
- + attr.event_mask = ExposureMask | StructureNotifyMask;
- + attr.border_pixel = BlackPixel( dpy, scr );
- + attr.background_pixel = BlackPixel( dpy, scr );
- + attr_flags = CWColormap | CWEventMask | CWBorderPixel | CWBackPixel;
- +
- + /* Create the window */
- + win = XCreateWindow( dpy, root, x,y, width, height, 0,
- + visinfo->depth, InputOutput,
- + visinfo->visual,
- + attr_flags, &attr);
- + if (!win) {
- + printf("Couldn't open window!\n");
- + exit(1);
- + }
- +
- + XStringListToTextProperty(&title, 1, &tp);
- + sh.flags = USPosition | USSize;
- + XSetWMProperties(dpy, win, &tp, &tp, 0, 0, &sh, 0, 0);
- + XMapWindow(dpy, win);
- + while (1) {
- + XNextEvent( dpy, &e );
- + if (e.type == MapNotify && e.xmap.window == win) {
- + break;
- + }
- + }
- +
- +
- + /*
- + * Now do the special Mesa/Xlib stuff!
- + */
- +
- + visual = XMesaCreateVisual( dpy, visinfo,
- + (GLboolean) color_flag,
- + GL_FALSE, /* alpha_flag */
- + GL_FALSE, /* db_flag */
- + GL_FALSE, /* stereo flag */
- + GL_FALSE, /* ximage_flag */
- + 0, /* depth size */
- + 0, /* stencil size */
- + 0,0,0,0, /* accum_size */
- + 0, /* num samples */
- + 0, /* level */
- + 0 /* caveat */
- + );
- + if (!visual) {
- + printf("Couldn't create Mesa/X visual!\n");
- + exit(1);
- + }
- +
- + /* Create a Mesa rendering context */
- + context = XMesaCreateContext( visual,
- + NULL /* share_list */
- + );
- + if (!context) {
- + printf("Couldn't create Mesa/X context!\n");
- + exit(1);
- + }
- +
- + buffer = XMesaCreateWindowBuffer( visual, win );
- + if (!buffer) {
- + printf("Couldn't create Mesa/X buffer!\n");
- + exit(1);
- + }
- +
- +
- + XMesaMakeCurrent( context, buffer );
- +
- + /* Ready to render! */
- +}
- +
- +
- +
- +static void draw_cube( void )
- +{
- + /* X faces */
- + glIndexi( Red );
- + glColor3f( 1.0, 0.0, 0.0 );
- + glBegin( GL_POLYGON );
- + glVertex3f( 1.0, 1.0, 1.0 );
- + glVertex3f( 1.0, -1.0, 1.0 );
- + glVertex3f( 1.0, -1.0, -1.0 );
- + glVertex3f( 1.0, 1.0, -1.0 );
- + glEnd();
- +
- + glBegin( GL_POLYGON );
- + glVertex3f( -1.0, 1.0, 1.0 );
- + glVertex3f( -1.0, 1.0, -1.0 );
- + glVertex3f( -1.0, -1.0, -1.0 );
- + glVertex3f( -1.0, -1.0, 1.0 );
- + glEnd();
- +
- + /* Y faces */
- + glIndexi( Green );
- + glColor3f( 0.0, 1.0, 0.0 );
- + glBegin( GL_POLYGON );
- + glVertex3f( 1.0, 1.0, 1.0 );
- + glVertex3f( 1.0, 1.0, -1.0 );
- + glVertex3f( -1.0, 1.0, -1.0 );
- + glVertex3f( -1.0, 1.0, 1.0 );
- + glEnd();
- +
- + glBegin( GL_POLYGON );
- + glVertex3f( 1.0, -1.0, 1.0 );
- + glVertex3f( -1.0, -1.0, 1.0 );
- + glVertex3f( -1.0, -1.0, -1.0 );
- + glVertex3f( 1.0, -1.0, -1.0 );
- + glEnd();
- +
- + /* Z faces */
- + glIndexi( Blue );
- + glColor3f( 0.0, 0.0, 1.0 );
- + glBegin( GL_POLYGON );
- + glVertex3f( 1.0, 1.0, 1.0 );
- + glVertex3f( -1.0, 1.0, 1.0 );
- + glVertex3f( -1.0, -1.0, 1.0 );
- + glVertex3f( 1.0, -1.0, 1.0 );
- + glEnd();
- +
- + glBegin( GL_POLYGON );
- + glVertex3f( 1.0, 1.0, -1.0 );
- + glVertex3f( 1.0,-1.0, -1.0 );
- + glVertex3f( -1.0,-1.0, -1.0 );
- + glVertex3f( -1.0, 1.0, -1.0 );
- + glEnd();
- +}
- +
- +
- +
- +
- +static void display_loop( void )
- +{
- + GLfloat xrot, yrot, zrot;
- +
- + xrot = yrot = zrot = 0.0;
- +
- + glClearColor( 0.0, 0.0, 0.0, 0.0 );
- + glClearIndex( Black );
- +
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glFrustum( -1.0, 1.0, -1.0, 1.0, 1.0, 10.0 );
- + glTranslatef( 0.0, 0.0, -5.0 );
- +
- + glMatrixMode( GL_MODELVIEW );
- + glLoadIdentity();
- +
- + glCullFace( GL_BACK );
- + glEnable( GL_CULL_FACE );
- +
- + glShadeModel( GL_FLAT );
- +
- + while (1) {
- + glClear( GL_COLOR_BUFFER_BIT );
- + glPushMatrix();
- + glRotatef( xrot, 1.0, 0.0, 0.0 );
- + glRotatef( yrot, 0.0, 1.0, 0.0 );
- + glRotatef( zrot, 0.0, 0.0, 1.0 );
- +
- + draw_cube();
- +
- + glPopMatrix();
- + glFinish();
- +
- + xrot += 10.0;
- + yrot += 7.0;
- + zrot -= 3.0;
- + }
- +
- +}
- +
- +
- +
- +
- +int main( int argc, char *argv[] )
- +{
- + int mode = 0;
- +
- + if (argc >= 2)
- + {
- + if (strcmp(argv[1],"-ci")==0)
- + mode = 0;
- + else if (strcmp(argv[1],"-rgb")==0)
- + mode = 1;
- + else
- + {
- + printf("Bad flag: %s\n", argv[1]);
- + printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n");
- + exit(1);
- + }
- + }
- + else
- + {
- + printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n");
- + printf("Defaulting to 8-bit color index\n");
- + }
- +
- + make_window( argv[0], mode );
- +
- + display_loop();
- + return 0;
- +}
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/xfont.c Mesa-7.8.1.patched/progs/xdemos/xfont.c
- --- Mesa-7.8.1/progs/xdemos/xfont.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/xfont.c 2010-06-13 13:45:06.788792936 +0200
- @@ -0,0 +1,206 @@
- +
- +/*
- + * Mesa 3-D graphics library
- + *
- + * Copyright (C) 1999 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * Example of using glXUseXFont().
- + * 5 November 1999
- + * Brian Paul
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +
- +
- +static const char *ProgramName = "xfont";
- +
- +static const char *FontName = "fixed";
- +
- +static GLuint FontBase = 0;
- +
- +
- +
- +static void redraw( Display *dpy, Window w )
- +{
- + static const char *text = "This is glXUseXFont()";
- +
- + glClear( GL_COLOR_BUFFER_BIT );
- +
- + /* triangle */
- + glColor3f( 0.2, 0.2, 1.0 );
- + glBegin(GL_TRIANGLES);
- + glVertex2f( 0, 0.8 );
- + glVertex2f( -0.8, -0.7 );
- + glVertex2f( 0.8, -0.7 );
- + glEnd();
- +
- + /* text */
- + glColor3f( 1, 1, 1 );
- + glRasterPos2f(-0.8, 0);
- + glListBase(FontBase);
- + glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text);
- +
- + glXSwapBuffers( dpy, w );
- +}
- +
- +
- +
- +static void resize( unsigned int width, unsigned int height )
- +{
- + glViewport( 0, 0, width, height );
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
- +}
- +
- +
- +
- +static void setup_font( Display *dpy )
- +{
- + XFontStruct *fontInfo;
- + Font id;
- + unsigned int first, last;
- +
- + fontInfo = XLoadQueryFont(dpy, FontName);
- + if (!fontInfo) {
- + printf("Error: font %s not found\n", FontName);
- + exit(0);
- + }
- +
- + id = fontInfo->fid;
- + first = fontInfo->min_char_or_byte2;
- + last = fontInfo->max_char_or_byte2;
- +
- + FontBase = glGenLists((GLuint) last + 1);
- + if (!FontBase) {
- + printf("Error: unable to allocate display lists\n");
- + exit(0);
- + }
- + glXUseXFont(id, first, last - first + 1, FontBase + first);
- +}
- +
- +static Window make_rgb_db_window( Display *dpy, int xpos, int ypos,
- + unsigned int width, unsigned int height )
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, ProgramName, ProgramName,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- +
- + glXMakeCurrent( dpy, win, ctx );
- +
- + return win;
- +}
- +
- +
- +static void event_loop( Display *dpy )
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent( dpy, &event );
- +
- + switch (event.type) {
- + case Expose:
- + redraw( dpy, event.xany.window );
- + break;
- + case ConfigureNotify:
- + resize( event.xconfigure.width, event.xconfigure.height );
- + break;
- + case KeyPress:
- + exit(0);
- + default:
- + ; /* no-op */
- + }
- + }
- +}
- +
- +
- +
- +int main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + Window win;
- +
- + dpy = XOpenDisplay(NULL);
- +
- + win = make_rgb_db_window( dpy, 0, 0, 300, 300 );
- + setup_font( dpy );
- +
- + glShadeModel( GL_FLAT );
- + glClearColor( 0.5, 0.5, 1.0, 1.0 );
- +
- + XMapWindow( dpy, win );
- +
- + event_loop( dpy );
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/xrotfontdemo.c Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c
- --- Mesa-7.8.1/progs/xdemos/xrotfontdemo.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,220 @@
- +/*
- + * Mesa 3-D graphics library
- + *
- + * Copyright (C) 1999 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/*
- + * Example of using glXUseRotatedXFontMESA().
- + * 24 Jan 2004
- + * Brian Paul
- + */
- +
- +
- +#include <GL/gl.h>
- +#include <GL/glx.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include "xuserotfont.h"
- +
- +
- +static const char *ProgramName = "xfont";
- +
- +static const char *FontName = "fixed";
- +
- +static GLuint FontBase[4];
- +
- +
- +static void redraw( Display *dpy, Window w )
- +{
- + static const char *text = " Rotated bitmap text";
- + int i;
- +
- + glClear( GL_COLOR_BUFFER_BIT );
- +
- + /* triangle */
- + glColor3f( 0.2, 0.2, 1.0 );
- + glBegin(GL_TRIANGLES);
- + glVertex2f( -0.8, 0.7 );
- + glVertex2f( -0.8, -0.7 );
- + glVertex2f( 0.8, 0.0 );
- + glEnd();
- +
- + /* marker */
- + glColor3f( 0, 1, 0 );
- + glBegin(GL_POINTS);
- + glVertex2f(0, 0);
- + glEnd();
- +
- + /* text */
- + glColor3f( 1, 1, 1 );
- +
- + for (i = 0; i < 4; i++) {
- + glRasterPos2f(0, 0);
- + glListBase(FontBase[i]);
- + glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text);
- + }
- +
- + glXSwapBuffers( dpy, w );
- +}
- +
- +
- +
- +static void resize( unsigned int width, unsigned int height )
- +{
- + glViewport( 0, 0, width, height );
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
- +}
- +
- +
- +
- +static void setup_font( Display *dpy )
- +{
- + XFontStruct *fontInfo;
- + Font id;
- + unsigned int first, last;
- + int i;
- +
- + fontInfo = XLoadQueryFont(dpy, FontName);
- + if (!fontInfo) {
- + printf("Error: font %s not found\n", FontName);
- + exit(0);
- + }
- +
- + id = fontInfo->fid;
- + first = fontInfo->min_char_or_byte2;
- + last = fontInfo->max_char_or_byte2;
- +
- + for (i = 0; i < 4; i++) {
- + FontBase[i] = glGenLists((GLuint) last + 1);
- + if (!FontBase[i]) {
- + printf("Error: unable to allocate display lists\n");
- + exit(0);
- + }
- + glXUseRotatedXFontMESA(id, first, last - first + 1, FontBase[i] + first,
- + i * 90);
- + }
- +}
- +
- +
- +static Window make_rgb_db_window( Display *dpy, int xpos, int ypos,
- + unsigned int width, unsigned int height )
- +{
- + int attrib[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attrib );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + {
- + XSizeHints sizehints;
- + sizehints.x = xpos;
- + sizehints.y = ypos;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, ProgramName, ProgramName,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- +
- + glXMakeCurrent( dpy, win, ctx );
- +
- + return win;
- +}
- +
- +
- +static void event_loop( Display *dpy )
- +{
- + XEvent event;
- +
- + while (1) {
- + XNextEvent( dpy, &event );
- +
- + switch (event.type) {
- + case Expose:
- + redraw( dpy, event.xany.window );
- + break;
- + case ConfigureNotify:
- + resize( event.xconfigure.width, event.xconfigure.height );
- + break;
- + case KeyPress:
- + exit(0);
- + default:
- + ; /* no-op */
- + }
- + }
- +}
- +
- +
- +
- +int main( int argc, char *argv[] )
- +{
- + Display *dpy;
- + Window win;
- +
- + dpy = XOpenDisplay(NULL);
- +
- + win = make_rgb_db_window( dpy, 0, 0, 300, 300 );
- + setup_font( dpy );
- +
- + glShadeModel( GL_FLAT );
- + glClearColor( 0.5, 0.5, 1.0, 1.0 );
- +
- + XMapWindow( dpy, win );
- +
- + event_loop( dpy );
- + return 0;
- +}
- diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.c Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c
- --- Mesa-7.8.1/progs/xdemos/xuserotfont.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,399 @@
- +/*
- + * Mesa 3-D graphics library
- + * Version: 6.1
- + *
- + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included
- + * in all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- + */
- +
- +
- +/* \file xuserotfont.c
- + *
- + * A function like glXUseXFont() but takes a 0, 90, 180 or 270 degree
- + * rotation angle for rotated text display.
- + *
- + * Based on Mesa's glXUseXFont implementation written by Thorsten Ohl.
- + */
- +
- +#include <assert.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <GL/glx.h>
- +#include "xuserotfont.h"
- +
- +
- +/**
- + * Generate OpenGL-compatible bitmap by drawing an X character glyph
- + * to an off-screen pixmap, then getting the image and testing pixels.
- + * \param width bitmap width in pixels
- + * \param height bitmap height in pixels
- + */
- +static void
- +fill_bitmap(Display *dpy, Pixmap pixmap, GC gc,
- + unsigned int bitmapWidth, unsigned int bitmapHeight,
- + unsigned int charWidth, unsigned int charHeight,
- + int xPos, int yPos, unsigned int c, GLubyte * bitmap,
- + int rotation)
- +{
- + const int bytesPerRow = (bitmapWidth + 7) / 8;
- + XImage *image;
- + XChar2b char2b;
- +
- + /* clear pixmap to 0 */
- + XSetForeground(dpy, gc, 0);
- + XFillRectangle(dpy, pixmap, gc, 0, 0, charWidth, charHeight);
- +
- + /* The glyph is drawn snug up against the left/top edges of the pixmap */
- + XSetForeground(dpy, gc, 1);
- + char2b.byte1 = (c >> 8) & 0xff;
- + char2b.byte2 = (c & 0xff);
- + XDrawString16(dpy, pixmap, gc, xPos, yPos, &char2b, 1);
- +
- + /* initialize GL bitmap */
- + memset(bitmap, 0, bytesPerRow * bitmapHeight);
- +
- + image = XGetImage(dpy, pixmap, 0, 0, charWidth, charHeight, 1, XYPixmap);
- + if (image) {
- + /* Set appropriate bits in the GL bitmap.
- + * Note: X11 and OpenGL are upside down wrt each other).
- + */
- + unsigned int x, y;
- + if (rotation == 0) {
- + for (y = 0; y < charHeight; y++) {
- + for (x = 0; x < charWidth; x++) {
- + if (XGetPixel(image, x, y)) {
- + int y2 = bitmapHeight - y - 1;
- + bitmap[bytesPerRow * y2 + x / 8] |= (1 << (7 - (x % 8)));
- + }
- + }
- + }
- + }
- + else if (rotation == 90) {
- + for (y = 0; y < charHeight; y++) {
- + for (x = 0; x < charWidth; x++) {
- + if (XGetPixel(image, x, y)) {
- + int x2 = y;
- + int y2 = x;
- + bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8)));
- + }
- + }
- + }
- + }
- + else if (rotation == 180) {
- + for (y = 0; y < charHeight; y++) {
- + for (x = 0; x < charWidth; x++) {
- + if (XGetPixel(image, x, y)) {
- + int x2 = charWidth - x - 1;
- + bitmap[bytesPerRow * y + x2 / 8] |= (1 << (7 - (x2 % 8)));
- + }
- + }
- + }
- + }
- + else {
- + assert(rotation == 270);
- + for (y = 0; y < charHeight; y++) {
- + for (x = 0; x < charWidth; x++) {
- + if (XGetPixel(image, x, y)) {
- + int x2 = charHeight - y - 1;
- + int y2 = charWidth - x - 1;
- + bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8)));
- + }
- + }
- + }
- + }
- + XDestroyImage(image);
- + }
- +}
- +
- +
- +/*
- + * Determine if a given glyph is valid and return the
- + * corresponding XCharStruct.
- + */
- +static const XCharStruct *
- +isvalid(const XFontStruct * fs, unsigned int which)
- +{
- + unsigned int rows, pages;
- + unsigned int byte1 = 0, byte2 = 0;
- + int i, valid = 1;
- +
- + rows = fs->max_byte1 - fs->min_byte1 + 1;
- + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
- +
- + if (rows == 1) {
- + /* "linear" fonts */
- + if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
- + valid = 0;
- + }
- + else {
- + /* "matrix" fonts */
- + byte2 = which & 0xff;
- + byte1 = which >> 8;
- + if ((fs->min_char_or_byte2 > byte2) ||
- + (fs->max_char_or_byte2 < byte2) ||
- + (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
- + valid = 0;
- + }
- +
- + if (valid) {
- + if (fs->per_char) {
- + if (rows == 1) {
- + /* "linear" fonts */
- + return fs->per_char + (which - fs->min_char_or_byte2);
- + }
- + else {
- + /* "matrix" fonts */
- + i = ((byte1 - fs->min_byte1) * pages) +
- + (byte2 - fs->min_char_or_byte2);
- + return fs->per_char + i;
- + }
- + }
- + else {
- + return &fs->min_bounds;
- + }
- + }
- + return NULL;
- +}
- +
- +
- +void
- +glXUseRotatedXFontMESA(Font font, int first, int count, int listbase,
- + int rotation)
- +{
- + Display *dpy;
- + Window win;
- + Pixmap pixmap;
- + GC gc;
- + XFontStruct *fs;
- + GLint swapbytes, lsbfirst, rowlength;
- + GLint skiprows, skippixels, alignment;
- + unsigned int maxCharWidth, maxCharHeight;
- + GLubyte *bm;
- + int i;
- +
- + if (rotation != 0 &&
- + rotation != 90 &&
- + rotation != 180 &&
- + rotation != 270)
- + return;
- +
- + dpy = glXGetCurrentDisplay();
- + if (!dpy)
- + return; /* I guess glXMakeCurrent wasn't called */
- + win = RootWindow(dpy, DefaultScreen(dpy));
- +
- + fs = XQueryFont(dpy, font);
- + if (!fs) {
- + /*
- + _mesa_error(NULL, GL_INVALID_VALUE,
- + "Couldn't get font structure information");
- + */
- + return;
- + }
- +
- + /* Allocate a GL bitmap that can fit any character */
- + maxCharWidth = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
- + maxCharHeight = fs->max_bounds.ascent + fs->max_bounds.descent;
- + /* use max, in case we're rotating */
- + if (rotation == 90 || rotation == 270) {
- + /* swap width/height */
- + bm = (GLubyte *) malloc((maxCharHeight + 7) / 8 * maxCharWidth);
- + }
- + else {
- + /* normal or upside down */
- + bm = (GLubyte *) malloc((maxCharWidth + 7) / 8 * maxCharHeight);
- + }
- + if (!bm) {
- + XFreeFontInfo(NULL, fs, 1);
- + /*
- + _mesa_error(NULL, GL_OUT_OF_MEMORY,
- + "Couldn't allocate bitmap in glXUseXFont()");
- + */
- + return;
- + }
- +
- +#if 0
- + /* get the page info */
- + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
- + firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
- + lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
- + rows = fs->max_byte1 - fs->min_byte1 + 1;
- + unsigned int first_char, last_char, pages, rows;
- +#endif
- +
- + /* Save the current packing mode for bitmaps. */
- + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
- + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
- + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
- + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
- + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
- + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
- +
- + /* Enforce a standard packing mode which is compatible with
- + fill_bitmap() from above. This is actually the default mode,
- + except for the (non)alignment. */
- + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
- + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
- + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
- + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
- + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- +
- + /* Create pixmap and GC */
- + pixmap = XCreatePixmap(dpy, win, maxCharWidth, maxCharHeight, 1);
- + {
- + XGCValues values;
- + unsigned long valuemask;
- + values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
- + values.background = WhitePixel(dpy, DefaultScreen(dpy));
- + values.font = fs->fid;
- + valuemask = GCForeground | GCBackground | GCFont;
- + gc = XCreateGC(dpy, pixmap, valuemask, &values);
- + }
- +
- +#ifdef DEBUG_XROT
- + if (debug_xfonts)
- + dump_font_struct(fs);
- +#endif
- +
- + for (i = 0; i < count; i++) {
- + const unsigned int c = first + i;
- + const int list = listbase + i;
- + unsigned int charWidth, charHeight;
- + unsigned int bitmapWidth = 0, bitmapHeight = 0;
- + GLfloat xOrig, yOrig, xStep, yStep, dtemp;
- + const XCharStruct *ch;
- + int xPos, yPos;
- + int valid;
- +
- + /* check on index validity and get the bounds */
- + ch = isvalid(fs, c);
- + if (!ch) {
- + ch = &fs->max_bounds;
- + valid = 0;
- + }
- + else {
- + valid = 1;
- + }
- +
- +#ifdef DEBUG_XROT
- + if (debug_xfonts) {
- + char s[7];
- + sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
- + dump_char_struct(ch, s);
- + }
- +#endif
- +
- + /* glBitmap()' parameters:
- + straight from the glXUseXFont(3) manpage. */
- + charWidth = ch->rbearing - ch->lbearing;
- + charHeight = ch->ascent + ch->descent;
- + xOrig = -ch->lbearing;
- + yOrig = ch->descent;
- + xStep = ch->width;
- + yStep = 0;
- +
- + /* X11's starting point. */
- + xPos = -ch->lbearing;
- + yPos = ch->ascent;
- +
- + /* Apply rotation */
- + switch (rotation) {
- + case 0:
- + /* nothing */
- + bitmapWidth = charWidth;
- + bitmapHeight = charHeight;
- + break;
- + case 90:
- + /* xStep, yStep */
- + dtemp = xStep;
- + xStep = -yStep;
- + yStep = dtemp;
- + /* xOrig, yOrig */
- + yOrig = xOrig;
- + xOrig = charHeight - (charHeight - yPos);
- + /* width, height */
- + bitmapWidth = charHeight;
- + bitmapHeight = charWidth;
- + break;
- + case 180:
- + /* xStep, yStep */
- + xStep = -xStep;
- + yStep = -yStep;
- + /* xOrig, yOrig */
- + xOrig = charWidth - xOrig - 1;
- + yOrig = charHeight - yOrig - 1;
- + bitmapWidth = charWidth;
- + bitmapHeight = charHeight;
- + break;
- + case 270:
- + /* xStep, yStep */
- + dtemp = xStep;
- + xStep = yStep;
- + yStep = -dtemp;
- + /* xOrig, yOrig */
- + dtemp = yOrig;
- + yOrig = charWidth - xOrig;
- + xOrig = dtemp;
- + /* width, height */
- + bitmapWidth = charHeight;
- + bitmapHeight = charWidth;
- + break;
- + default:
- + /* should never get here */
- + ;
- + }
- +
- + glNewList(list, GL_COMPILE);
- + if (valid && bitmapWidth > 0 && bitmapHeight > 0) {
- +
- + fill_bitmap(dpy, pixmap, gc, bitmapWidth, bitmapHeight,
- + charWidth, charHeight,
- + xPos, yPos, c, bm, rotation);
- +
- + glBitmap(bitmapWidth, bitmapHeight, xOrig, yOrig, xStep, yStep, bm);
- +
- +#ifdef DEBUG_XROT
- + if (debug_xfonts) {
- + printf("width/height = %u/%u\n", bitmapWidth, bitmapHeight);
- + dump_bitmap(bitmapWidth, bitmapHeight, bm);
- + }
- +#endif
- + }
- + else {
- + glBitmap(0, 0, 0.0, 0.0, xStep, yStep, NULL);
- + }
- + glEndList();
- + }
- +
- + free(bm);
- + XFreeFontInfo(NULL, fs, 1);
- + XFreePixmap(dpy, pixmap);
- + XFreeGC(dpy, gc);
- +
- + /* Restore saved packing modes. */
- + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
- + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
- + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
- + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
- + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
- + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
- +}
- +
- +
- diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.h Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h
- --- Mesa-7.8.1/progs/xdemos/xuserotfont.h 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,12 @@
- +#ifndef XUSEROTFONT_H
- +#define XUSEROTFONT_H
- +
- +#include <X11/Xlib.h>
- +
- +
- +extern void
- +glXUseRotatedXFontMESA(Font font, int first, int count, int listbase,
- + int rotation);
- +
- +
- +#endif
- diff -Naurp Mesa-7.8.1/progs/xdemos/yuvrect_client.c Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c
- --- Mesa-7.8.1/progs/xdemos/yuvrect_client.c 1970-01-01 01:00:00.000000000 +0100
- +++ Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c 2010-06-13 13:45:06.789793146 +0200
- @@ -0,0 +1,326 @@
- +/*
- + * Test the GL_NV_texture_rectangle and GL_MESA_ycrcb_texture extensions and GLX_MESA_allocate-memory
- + *
- + * Dave Airlie - Feb 2005
- + */
- +
- +#include <assert.h>
- +#include <math.h>
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <X11/Xlib.h>
- +#include <X11/keysym.h>
- +#define GL_GLEXT_PROTOTYPES
- +#include <GL/glx.h>
- +
- +#include "../util/readtex.c" /* I know, this is a hack. */
- +
- +#define TEXTURE_FILE "../images/girl2.rgb"
- +
- +static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
- +static GLint ImgWidth, ImgHeight;
- +static GLushort *ImageYUV = NULL;
- +static void *glx_memory;
- +
- +static void DrawObject(void)
- +{
- + glBegin(GL_QUADS);
- +
- + glTexCoord2f(0, 0);
- + glVertex2f(-1.0, -1.0);
- +
- + glTexCoord2f(ImgWidth, 0);
- + glVertex2f(1.0, -1.0);
- +
- + glTexCoord2f(ImgWidth, ImgHeight);
- + glVertex2f(1.0, 1.0);
- +
- + glTexCoord2f(0, ImgHeight);
- + glVertex2f(-1.0, 1.0);
- +
- + glEnd();
- +}
- +
- +
- +static void scr_Display( void )
- +{
- + glClear( GL_COLOR_BUFFER_BIT );
- +
- + glPushMatrix();
- + glRotatef(Xrot, 1.0, 0.0, 0.0);
- + glRotatef(Yrot, 0.0, 1.0, 0.0);
- + glRotatef(Zrot, 0.0, 0.0, 1.0);
- + DrawObject();
- + glPopMatrix();
- +
- +}
- +
- +
- +static void Reshape( int width, int height )
- +{
- + glViewport( 0, 0, width, height );
- + glMatrixMode( GL_PROJECTION );
- + glLoadIdentity();
- + glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
- + glMatrixMode( GL_MODELVIEW );
- + glLoadIdentity();
- + glTranslatef( 0.0, 0.0, -15.0 );
- +}
- +
- +static int queryClient(Display *dpy, int screen)
- +{
- +#ifdef GLX_MESA_allocate_memory
- + char *extensions;
- +
- + extensions = (char *)glXQueryExtensionsString(dpy, screen);
- + if (!extensions || !strstr(extensions,"GLX_MESA_allocate_memory")) {
- + return 0;
- + }
- +
- + return 1;
- +#else
- + return 0;
- +#endif
- +}
- +
- +static int
- +query_extension(char* extName) {
- + char *p = (char *) glGetString(GL_EXTENSIONS);
- + char *end = p + strlen(p);
- + while (p < end) {
- + int n = strcspn(p, " ");
- + if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
- + return GL_TRUE;
- + p += (n + 1);
- + }
- + return GL_FALSE;
- +}
- +
- +static void Init( int argc, char *argv[] , Display *dpy, int screen, Window win)
- +{
- + GLuint texObj = 100;
- + const char *file;
- + void *glx_memory;
- +
- + if (!query_extension("GL_NV_texture_rectangle")) {
- + printf("Sorry, GL_NV_texture_rectangle is required\n");
- + exit(0);
- + }
- +
- + if (!query_extension("GL_MESA_ycbcr_texture")) {
- + printf("Sorry, GL_MESA_ycbcr_texture is required\n");
- + exit(0);
- + }
- +
- + if (!queryClient(dpy, screen)) {
- + printf("Sorry, GLX_MESA_allocate_memory is required\n");
- + exit(0);
- + }
- +
- + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
- + glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj);
- +#ifdef LINEAR_FILTER
- + /* linear filtering looks much nicer but is much slower for Mesa */
- + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- +#else
- + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- +#endif
- +
- + if (argc > 1)
- + file = argv[1];
- + else
- + file = TEXTURE_FILE;
- +
- + ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight);
- + if (!ImageYUV) {
- + printf("Couldn't read %s\n", TEXTURE_FILE);
- + exit(0);
- + }
- +
- + glx_memory = glXAllocateMemoryMESA(dpy, screen, ImgWidth * ImgHeight * 2, 0, 0 ,0);
- + if (!glx_memory)
- + {
- + fprintf(stderr,"Failed to allocate MESA memory\n");
- + exit(-1);
- + }
- +
- + memcpy(glx_memory, ImageYUV, ImgWidth * ImgHeight * 2);
- +
- + printf("Image: %dx%d\n", ImgWidth, ImgHeight);
- +
- + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0,
- + GL_YCBCR_MESA, ImgWidth, ImgHeight, 0,
- + GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_APPLE, glx_memory);
- +
- + assert(glGetError() == GL_NO_ERROR);
- +
- + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- +
- + glEnable(GL_TEXTURE_RECTANGLE_NV);
- +
- + glShadeModel(GL_FLAT);
- + glClearColor(0.3, 0.3, 0.4, 1.0);
- +
- +}
- +
- +/*
- + * Create an RGB, double-buffered window.
- + * Return the window and context handles.
- + */
- +static void
- +make_window( Display *dpy, const char *name,
- + int x, int y, int width, int height,
- + Window *winRet, GLXContext *ctxRet)
- +{
- + int attribs[] = { GLX_RGBA,
- + GLX_RED_SIZE, 1,
- + GLX_GREEN_SIZE, 1,
- + GLX_BLUE_SIZE, 1,
- + GLX_DOUBLEBUFFER,
- + GLX_DEPTH_SIZE, 1,
- + None };
- + int scrnum;
- + XSetWindowAttributes attr;
- + unsigned long mask;
- + Window root;
- + Window win;
- + GLXContext ctx;
- + XVisualInfo *visinfo;
- +
- + scrnum = DefaultScreen( dpy );
- + root = RootWindow( dpy, scrnum );
- +
- + visinfo = glXChooseVisual( dpy, scrnum, attribs );
- + if (!visinfo) {
- + printf("Error: couldn't get an RGB, Double-buffered visual\n");
- + exit(1);
- + }
- +
- + /* window attributes */
- + attr.background_pixel = 0;
- + attr.border_pixel = 0;
- + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
- + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- + attr.override_redirect = 0;
- + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
- +
- + win = XCreateWindow( dpy, root, 0, 0, width, height,
- + 0, visinfo->depth, InputOutput,
- + visinfo->visual, mask, &attr );
- +
- + /* set hints and properties */
- + {
- + XSizeHints sizehints;
- + sizehints.x = x;
- + sizehints.y = y;
- + sizehints.width = width;
- + sizehints.height = height;
- + sizehints.flags = USSize | USPosition;
- + XSetNormalHints(dpy, win, &sizehints);
- + XSetStandardProperties(dpy, win, name, name,
- + None, (char **)NULL, 0, &sizehints);
- + }
- +
- + ctx = glXCreateContext( dpy, visinfo, NULL, True );
- + if (!ctx) {
- + printf("Error: glXCreateContext failed\n");
- + exit(1);
- + }
- +
- + XFree(visinfo);
- +
- + *winRet = win;
- + *ctxRet = ctx;
- +}
- +
- +
- +static void
- +event_loop(Display *dpy, Window win)
- +{
- + while (1) {
- + while (XPending(dpy) > 0) {
- + XEvent event;
- + XNextEvent(dpy, &event);
- + switch (event.type) {
- + case Expose:
- + /* we'll redraw below */
- + break;
- + case ConfigureNotify:
- + Reshape(event.xconfigure.width, event.xconfigure.height);
- + break;
- + case KeyPress:
- + {
- + char buffer[10];
- + int r, code;
- + code = XLookupKeysym(&event.xkey, 0);
- + r = XLookupString(&event.xkey, buffer, sizeof(buffer),
- + NULL, NULL);
- + if (buffer[0] == 27) {
- + /* escape */
- + return;
- +
- + }
- + }
- + }
- + }
- +
- + }
- +}
- +
- +
- +int
- +main(int argc, char *argv[])
- +{
- + Display *dpy;
- + Window win;
- + GLXContext ctx;
- + char *dpyName = NULL;
- + GLboolean printInfo = GL_FALSE;
- + int i;
- +
- + for (i = 1; i < argc; i++) {
- + if (strcmp(argv[i], "-display") == 0) {
- + dpyName = argv[i+1];
- + i++;
- + }
- + else if (strcmp(argv[i], "-info") == 0) {
- + printInfo = GL_TRUE;
- + }
- + else
- + printf("Warrning: unknown parameter: %s\n", argv[i]);
- + }
- +
- + dpy = XOpenDisplay(dpyName);
- + if (!dpy) {
- + printf("Error: couldn't open display %s\n",
- + XDisplayName(dpyName));
- + return -1;
- + }
- +
- + make_window(dpy, "yuvrect_client", 0, 0, 300, 300, &win, &ctx);
- + XMapWindow(dpy, win);
- + glXMakeCurrent(dpy, win, ctx);
- +
- + if (printInfo) {
- + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
- + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
- + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
- + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
- + }
- +
- + Init(argc, argv, dpy, DefaultScreen(dpy), win);
- +
- + scr_Display();
- + glXSwapBuffers(dpy, win);
- + event_loop(dpy, win);
- +
- + glXFreeMemoryMESA(dpy, DefaultScreen(dpy), glx_memory);
- + glXDestroyContext(dpy, ctx);
- + XDestroyWindow(dpy, win);
- + XCloseDisplay(dpy);
- +
- + return 0;
- +}
|