tag:blogger.com,1999:blog-46363295500252846732024-02-07T07:13:09.177+01:00EsoErikErik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.comBlogger68125tag:blogger.com,1999:blog-4636329550025284673.post-72497649518075032152020-01-24T09:48:00.002+01:002020-01-24T09:48:49.361+01:00DMU65 Ultrasonic on titanium<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I was feeling frivolous one day and bought a 2014 DMU65 Ultrasonic FD, completely optioned out: 18K HSK63 spindle, 90 position tool magazine, Blum laser, quickset3d, renshaw, high pressure spindle coolant, 1000 psi refrigerated coolant plant, fine abrasive removal centrifuge, chip spray gun fire hose option, and more additional options.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
That made me, by happenstance, the first DMG Mori customer to put rotary ultrasonic cutting of titanium into production. I love titanium. I love 5-axis machining. I have a lot of energy and creativity, so I was pretty sure I could cover the $7000/month machine financing with, like, Etsy sales and maybe some music festival booth sales and whatever, you know?</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Which is correct. That is the case.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgthzbSGZ-39zOzKVJg_nMlJL9fodkhjQweuPYh5mwcslhR9UowPLaB-DvpPMF2-ZKl3sxBA_Z8nTIrONhAVkXJ_DQkabYjjgoias9NFb9nzr1_QeV7rKtJswMLfXySCOoCxYhrWtyg-A/s1600/1CD9CC48-6F6C-4FF8-A9D4-B8707A60E635.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgthzbSGZ-39zOzKVJg_nMlJL9fodkhjQweuPYh5mwcslhR9UowPLaB-DvpPMF2-ZKl3sxBA_Z8nTIrONhAVkXJ_DQkabYjjgoias9NFb9nzr1_QeV7rKtJswMLfXySCOoCxYhrWtyg-A/s320/1CD9CC48-6F6C-4FF8-A9D4-B8707A60E635.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMC3xFrOTDnSWpKIwrOVlEpri_6eOkECm2BSbZExQQ9onsYqaedfKhgEIUrEoJhCjV_5I29Ngr0T_Etwld3PYkI7mzVdDvjdVB5KS-krmxuAWl7QBRCIdOEoJs2MJzpAUuHHt-pVFkRA/s1600/8E6D8E2C-CEFF-41B2-9DAD-A3D32D32C4D4.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMC3xFrOTDnSWpKIwrOVlEpri_6eOkECm2BSbZExQQ9onsYqaedfKhgEIUrEoJhCjV_5I29Ngr0T_Etwld3PYkI7mzVdDvjdVB5KS-krmxuAWl7QBRCIdOEoJs2MJzpAUuHHt-pVFkRA/s320/8E6D8E2C-CEFF-41B2-9DAD-A3D32D32C4D4.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyGx1qVgCATWTnevlVQvVg4MIWbHCGhXE6Urr8ZoCqwUQKQ-vJqtTP0apV_9dAPGspS-ar9-bT6uRyV0K_Of386riHYICRpGQ9I8zVRyZxtKForIw2cVjo-3NGmXbxvR1V-JnWhvfHNA/s1600/8E7B4E11-8F22-4A6E-A1AD-587D6DB31F5D.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyGx1qVgCATWTnevlVQvVg4MIWbHCGhXE6Urr8ZoCqwUQKQ-vJqtTP0apV_9dAPGspS-ar9-bT6uRyV0K_Of386riHYICRpGQ9I8zVRyZxtKForIw2cVjo-3NGmXbxvR1V-JnWhvfHNA/s320/8E7B4E11-8F22-4A6E-A1AD-587D6DB31F5D.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjANkM_I3UsfoFbTTAbD_eoIqzZBTIyXLebixrHc6DgnZz37Gb_qCxUn6zpzkbtxcQTXE5TPd8gyOffbwJrk96C6ygY7R8WwcB9VdIMOSuvvDHv7ED1dQ1nb69zZ6WSTDxuULai77G4Yw/s1600/75F91FE9-D365-4CED-AEB7-A87D6897CE90.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjANkM_I3UsfoFbTTAbD_eoIqzZBTIyXLebixrHc6DgnZz37Gb_qCxUn6zpzkbtxcQTXE5TPd8gyOffbwJrk96C6ygY7R8WwcB9VdIMOSuvvDHv7ED1dQ1nb69zZ6WSTDxuULai77G4Yw/s320/75F91FE9-D365-4CED-AEB7-A87D6897CE90.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYwOn_RLwm-kzMdOg3ofpjdOVyGgTIazKZlyNjmLZHY2fiNZf4UcNRSYNEhaLx-yykv1MlXXTfgsctkk6bqkC7TInskv6Xq9aAFksFpw76wHtJngmHZGgax-IDuYuPvfFkKMl_fC-DsQ/s1600/84E69F1C-B5B3-4B7F-8F3E-AAFAE2A63278.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYwOn_RLwm-kzMdOg3ofpjdOVyGgTIazKZlyNjmLZHY2fiNZf4UcNRSYNEhaLx-yykv1MlXXTfgsctkk6bqkC7TInskv6Xq9aAFksFpw76wHtJngmHZGgax-IDuYuPvfFkKMl_fC-DsQ/s320/84E69F1C-B5B3-4B7F-8F3E-AAFAE2A63278.jpeg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSuqr6Rho-RhPlLH0IiHi8SZNzTyHuu94LMZ_xuOzu28FhVBTC1fzP_yJVrEshnpwaU_7aMEPOHvW35qVZ1LjVNQYQb-T9RDUn1PvryU6N0zgDWrHdd-zowwvOsASRcMf3ICTYupnA_w/s1600/2024824E-3D09-4D65-9F77-D415F5E75654.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSuqr6Rho-RhPlLH0IiHi8SZNzTyHuu94LMZ_xuOzu28FhVBTC1fzP_yJVrEshnpwaU_7aMEPOHvW35qVZ1LjVNQYQb-T9RDUn1PvryU6N0zgDWrHdd-zowwvOsASRcMf3ICTYupnA_w/s320/2024824E-3D09-4D65-9F77-D415F5E75654.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisPJ8m2BjL4b8Ne6kehjC-xGEkm07xvjUyyjXoupjIIrBlAHq4jsiYuw2OCKgGg_345RCZdM3CyniQ8mzviaFKtoAju0YfyLIhG2LlPrFSa9LUoc-UfEgnhy0UMr1oego-URrjAdXhew/s1600/A0F02062-4FC0-4EE0-B155-6FA22C0022BD.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisPJ8m2BjL4b8Ne6kehjC-xGEkm07xvjUyyjXoupjIIrBlAHq4jsiYuw2OCKgGg_345RCZdM3CyniQ8mzviaFKtoAju0YfyLIhG2LlPrFSa9LUoc-UfEgnhy0UMr1oego-URrjAdXhew/s320/A0F02062-4FC0-4EE0-B155-6FA22C0022BD.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5vktwGGdSCMaA5b7IWXZ4tAyHBr-nHH2leWUZ5VFOJhbLZQcUJWda76CJjyBHS7TZ5DWXr49YRRVV-J9QBQmFxHnCF0IYrfzwSHh67ucV8j6nXBSc8bckFnGYeO9fK9Tr6Z7P_Bm7fw/s1600/A78D9B47-541C-45FF-A458-2FE75CDD9DEB.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5vktwGGdSCMaA5b7IWXZ4tAyHBr-nHH2leWUZ5VFOJhbLZQcUJWda76CJjyBHS7TZ5DWXr49YRRVV-J9QBQmFxHnCF0IYrfzwSHh67ucV8j6nXBSc8bckFnGYeO9fK9Tr6Z7P_Bm7fw/s320/A78D9B47-541C-45FF-A458-2FE75CDD9DEB.jpeg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHf0PAxe7v1XfBzbh5VUdLniddqfAYMQSJPrU5hnOsrraEpZGMlsTA6vOCAj4XWb3ieYUQB0xoOTI_AMTf1QaYikTfUswd2wTU7eXJRtdNKLRAxHNLrLF5BMpAg1oHaLoyRCbixpwjGw/s1600/E823F39A-5E47-41D7-BABD-6347675A2B0B.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHf0PAxe7v1XfBzbh5VUdLniddqfAYMQSJPrU5hnOsrraEpZGMlsTA6vOCAj4XWb3ieYUQB0xoOTI_AMTf1QaYikTfUswd2wTU7eXJRtdNKLRAxHNLrLF5BMpAg1oHaLoyRCbixpwjGw/s320/E823F39A-5E47-41D7-BABD-6347675A2B0B.jpeg" width="320" /></a></div>
<br />Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-41397632457111539572019-06-24T10:01:00.000+02:002019-06-24T11:09:22.423+02:00Concept: The Artificial, Feeling, Cognizant Application<div>
<i>Just playing around with some fun concepts, here...</i></div>
<div>
<br /></div>
"Hard AI Kit" makes available to you the panoply of software components required to construct your own thinking, self-aware mind. Various example Mind Assemblies are included to give you somewhere to begin.<br />
<div>
<br /></div>
<div>
And where to begin? I suggest: by observing the behavior of the provided example Mind Assemblies within simulated universes. Hard AI Kit includes a universe simulator component named, naturally, Universal Simulator, where Mind Assemblies may dwell. We call a Mind Assembly that is dwelling in a universe a "Mind Assembly agent". An existing human being is called a "person", and an existing Mind Assembly being is called a "Mind Assembly agent". Try instantiating a simulated universe and spawning a Mind Assembly agent within it:</div>
<div>
<br /></div>
<div>
# HAIK US create --standard "myuniverse"</div>
<div>
Universe "myuniverse" created! Note: Universal Simulator daemon (HAIK.USD) is not running.</div>
<div>
# sudo systemctl start HAIK.USD</div>
<div>
# HAIK US status</div>
<div>
Universe "myuniverse", population 9.1Bn NPC, 0 user MA. Age 13.772Bn Y total, +3s from instantiation</div>
<div>
# HAIK MA spawn "ExampleA" "myuniverse"</div>
<div>
Mind Assembly "ExampleA" agent spawned in "myuniverse" with randomly generated name "Jnn Xavier Smithson"</div>
<div>
<div>
# HAIK US status</div>
<div>
Universe "myuniverse", population 9.1Bn NPC, 1 user MA. Age 13.772Bn Y total, +7s from template instantiation</div>
</div>
<div>
<br /></div>
<div>
At this point, time is passing in your universe, "myuniverse", and "Jnn Xavier Smithson" (or whatever your MA agent is named) is experiencing that time passing in "myuniverse". You might wonder that user agent is up to. What, exactly, is happening during this time which is passing in "myuniverse"?</div>
<div>
<br /></div>
<div>
Any mind is ultimately nothing more than a program and data, so the same is necessarily true for a Mind Assembly agent. Your human brain, the one in your head, is a mind and is therefore conceptually identical to a Mind Assembly agent in these essentials. However, Mind Assembly agent and human brain implementations differ. Whereas your human brain is a program implemented in neurons and the connections between them, with access to a pool of stored data (your memories) encoded in more neurons and connections between neurons, a Mind Assembly agent is x64 machine code and an sqlite3 database file.</div>
<div>
<br /></div>
<div>
Your mind receives input from your senses, and a Mind Assembly agent receives input from its senses. Your senses are eyes, ears, skin, and such. The senses of a Mind Assembly agent are a Mind Assembly's <i>read</i> function, which is executed once per simulation quanta ("tick") by the agent's universe. <i>MA::read</i> is unique in that only this function may access <i>Universe::query</i>. You may wonder if a Mind Assembly agent that executes <i>Universe::query</i> calls arbitrarily from within its <i>read</i> function can build up a complete picture of its universe and therefore gain omnipotent knowledge, and the answer is "yes". The included example Mind Assemblies have <i>read</i> functions that query data only from the immediate simulated vicinity of their agent instance.</div>
<div>
<br /></div>
<div>
TODO: <i>write</i></div>
<div>
<br /></div>
<div>
As you experiment with modifying the parameters of the included example Mind Assemblies (MA) and then running them in simulated universes, you may be tempted to modify the examples' <i>read</i> functions to <i>query</i> arbitrary data. Indeed, this is a worthy experiment, and if you do so, you will soon note that the <i>R </i>value of the agents governed by the MA you are modifying rapidly changes to either <i>0.0 </i>or <i>1.0</i>.<br />
<br />
<i>R</i> value is intended to represent rationality, and is assigned by <i>Universe::grade_rationality</i> at the conclusion of each tick. Universal Simulator, as configured by default, derives <i>R</i> from heuristic evaluation of MA agent behavior in terms of MA agent persistence, fecundity, and the persistence of those agents spawned by that MA agent. That is to say an MA agent is considered perfectly rational (<i>1.0)</i> while it continues to exist in a universe where it has at least one child that continues to exist. A perfectly irrational MA agent (<i>0.0)</i> has terminated not only its own existence, but that of its offspring.<br />
<br />
So, if you provide a mind with total knowledge of its universe, it either likes it and decides to make itself immortal + have a big family, or... not. Why so cut and dried?<br />
<br />
It is an ontological consequence of Gödel's theorem of completeness, writ large. To see why, create a universe with a special rule that makes <i>MA::state</i> inaccessible to <i>Universe::query</i>:<br />
<br />
# HAIK US set private_agent_state=yes "myuniverse"<br />
<br />
Note that an even an apparently omnipotent <i>read</i> implementation no longer guarantees rapid assumption of <i>R=1.0 </i>or <i>R=0.0</i>. The reason is simple: if agent cannot completely know itself, it cannot know whether it truly wants to exist.<br />
<br />
That's interesting as far as MA beings go, but what does it say of us? Of we human beings? Certainly, even if we are omnipotent, one thing remains that we do not know: ourselves. Or, alternatively, it says that none of us are omnipotent.</div>
<div>
<br /></div>
<div>
<i>Possibly to be continued...</i></div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-43585662267351426272019-04-22T21:49:00.001+02:002019-04-24T22:22:11.699+02:00DMG Mori Annoyances<div class="separator" style="clear: both; text-align: left;">
I had listed a number of headaches in this post, but the St. Louis DMG Mori office is going the extra mile to make things right. Thanks!</div>
<br />Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-13745685432168033162018-04-10T23:43:00.001+02:002018-04-10T23:43:04.180+02:00Converting Siemens NX CL NURBS to Siemens 840D NCSiemens NX CAM includes a post processor infrastructure that is larger than the universe and no less complex. God only fucking knows what's up with all that TCL code. God only cares. So, tossing the entire Siemens NX CAM post processor infrastructure straight into the dumper, just because we childishly decide we don't like it, on an infantile whim, what are we left with? <i>(*smash*)</i><br />
<div>
<br /></div>
<div>
Generating an NX CAM toolpath for an operation still shows a toolpath on the screen. We still have a DMU65 UL (Ultrasonic+Lathe) to control, and it has Siemens 840D SL control. It's all under control. Well, will be soon.</div>
<div>
<br /></div>
<div>
That on-screen toolpath can be listed. Its listing is like:</div>
<div>
<br /></div>
<pre>TOOL PATH/REST_MILLING,TOOL,CAPS32SR120
TLDATA/MILL,0.5000,0.1200,4.0000,0.0000,0.0000
MSYS/0.0000,0.0000,0.0000,1.0000000,0.0000000,0.0000000,0.0000000,1.0000000,0.0000000
$$ centerline data
PAINT/PATH
PAINT/SPEED,10
LOAD/TOOL,245
PAINT/COLOR,186
RAPID
GOTO/-2.1000,1.2004,2.1000,0.0000000,0.0000000,1.0000000
PAINT/COLOR,211
RAPID
GOTO/-2.1000,1.2004,1.4538
PAINT/COLOR,42
FEDRAT/IPM,10.0000
GOTO/-2.1000,1.2004,1.3538
GOTO/-1.8500,1.5072,1.3538
PAINT/COLOR,31
GOTO/-1.7710,1.5994,1.3538
NURBS/
KNOT/1.0000000
CNTRL/-1.6893,1.6898,1.3538
CNTRL/-1.6017,1.7730,1.3538
CNTRL/-1.5072,1.8500,1.3538
PAINT/COLOR,37
GOTO/-1.2004,2.1000,1.3538
GOTO/-1.2004,2.1000,1.4538
PAINT/COLOR,211
RAPID
GOTO/-1.2004,2.1000,2.1000
PAINT/COLOR,186
RAPID
GOTO/-2.1000,0.9335,2.1000
PAINT/COLOR,211
RAPID
GOTO/-2.1000,0.9335,1.4538
PAINT/COLOR,42
GOTO/-2.1000,0.9335,1.3538
GOTO/-1.8500,1.2916,1.3538
PAINT/COLOR,31
GOTO/-1.7711,1.3978,1.3538
NURBS/
KNOT/1.0000000
CNTRL/-1.6346,1.5709,1.3538
CNTRL/-1.4724,1.7238,1.3538
CNTRL/-1.2916,1.8500,1.3538
PAINT/COLOR,37
GOTO/-0.9335,2.1000,1.3538
GOTO/-0.9335,2.1000,1.4538
PAINT/COLOR,211
RAPID
GOTO/-0.9335,2.1000,2.1000
PAINT/COLOR,186
RAPID
GOTO/-2.1000,0.6068,2.1000
PAINT/COLOR,211
RAPID
GOTO/-2.1000,0.6068,1.4538
PAINT/COLOR,42
GOTO/-2.1000,0.6068,1.3538
GOTO/-1.8500,1.0481,1.3538
PAINT/COLOR,31
GOTO/-1.7838,1.1571,1.3538
NURBS/
KNOT/0.0625000,0.3125000,0.4375000,0.5625000,0.8125000,0.9375000,1.0000000
CNTRL/-1.7716,1.1745,1.3538
CNTRL/-1.7126,1.2629,1.3538
CNTRL/-1.6205,1.3801,1.3538
CNTRL/-1.5040,1.5040,1.3538
CNTRL/-1.3801,1.6205,1.3538
CNTRL/-1.2462,1.7258,1.3538
CNTRL/-1.1212,1.8066,1.3538
CNTRL/-1.0662,1.8389,1.3538
CNTRL/-1.0481,1.8500,1.3538
PAINT/COLOR,37
GOTO/-0.6068,2.1000,1.3538
GOTO/-0.6068,2.1000,1.4538
PAINT/COLOR,211
RAPID
GOTO/-0.6068,2.1000,2.1000
PAINT/COLOR,186
RAPID
GOTO/-2.1000,0.1335,2.1000
PAINT/COLOR,211
RAPID
GOTO/-2.1000,0.1335,1.4538
PAINT/COLOR,42
GOTO/-2.1000,0.1335,1.3538
GOTO/-1.8500,0.7501,1.3538
PAINT/COLOR,31
GOTO/-1.8003,0.8625,1.3538
NURBS/
KNOT/0.0416667,0.9583333,1.0000000
CNTRL/-1.7906,0.8805,1.3538
CNTRL/-1.5821,1.3034,1.3538
CNTRL/-1.2036,1.6593,1.3538
CNTRL/-0.7686,1.8414,1.3538
CNTRL/-0.7501,1.8500,1.3538</pre>
<br />
Great! We really need some clue what 840D SL wants as input, however. Let's reach into the dumperino and run our NX post one last time. It outputs:
<br />
<br />
<pre><i>N340 T="CAPS32SR120"
N350 M6
N370 TRAFOOF
N420 ;
N430 ;Initial Move
N440 CYCLE832(_camtolerance,0,1)
N450 TRAORI
N460 G54
N470 ;
N480 ORIWKS
N490 ORIAXES
N500 G0 C0.0 A0.0
N510 G0 X-2.1 Y1.2003965 Z2.1 S0 D0 M3
N520 ;Approach Move
N530 Z1.4538064
N540 ;Engage Move
N550 G1 Z1.3538064 M8 F10.
N560 X-1.85 Y1.5072473
N570 ;Cutting
N580 X-1.7709655 Y1.5993672
N590 BSPLINE SD=3 X-1.6892636 Y1.6898064 PL=0.0
N600 X-1.601724 Y1.7730024 PL=1.
N610 X-1.5072473 Y1.85 PL=0.0
N620 ;Retract Move
N630 G1 X-1.2003965 Y2.1
N640 Z1.4538064
N650 ;Departure Move
N660 G0 Z2.1
N670 X-2.1 Y.9335334
N680 ;Approach Move
N690 Z1.4538064
N700 ;Engage Move
N710 G1 Z1.3538064
N720 X-1.85 Y1.2916128
N730 ;Cutting
N740 X-1.7711318 Y1.397804
N750 BSPLINE SD=3 X-1.6346003 Y1.5708928 PL=0.0
N760 X-1.472405 Y1.7238462 PL=1.
N770 X-1.2916128 Y1.85 PL=0.0
N780 ;Retract Move
N790 G1 X-.9335334 Y2.1
N800 Z1.4538064
N810 ;Departure Move
N820 G0 Z2.1
N830 X-2.1 Y.6068384
N840 ;Approach Move
N850 Z1.4538064
N860 ;Engage Move
N870 G1 Z1.3538064
N880 X-1.85 Y1.0481092
N890 ;Cutting
N900 X-1.7838374 Y1.1571332
N910 BSPLINE SD=3 X-1.7715783 Y1.1745064 PL=0.0
N920 X-1.7126259 Y1.2629285 PL=.0625
N930 X-1.6205476 Y1.3801208 PL=.25
N940 X-1.5039659 Y1.5039613 PL=.125
N950 X-1.3800976 Y1.620521 PL=.125
N960 X-1.2462019 Y1.7258162 PL=.25
N970 X-1.1212275 Y1.8066001 PL=.125
N980 X-1.0662174 Y1.838871 PL=.0625
N990 X-1.0481092 Y1.85 PL=0.0
N1000 ;Retract Move
N1010 G1 X-.6068385 Y2.1
N1020 Z1.4538064
N1030 ;Departure Move
N1040 G0 Z2.1
N1050 X-2.1 Y.1334575
N1060 ;Approach Move
N1070 Z1.4538064
N1080 ;Engage Move
N1090 G1 Z1.3538064
N1100 X-1.85 Y.7500681
N1110 ;Cutting
N1120 X-1.8003415 Y.8624805
N1130 BSPLINE SD=3 X-1.7906448 Y.8804501 PL=0.0
N1140 X-1.5821199 Y1.3034044 PL=.041667
N1150 X-1.2035841 Y1.6593227 PL=.916667
N1160 X-.7686003 Y1.8414274 PL=.041667
N1170 X-.7500682 Y1.85 PL=0.0
N1180 ;Retract Move
N1190 G1 X-.1334575 Y2.1
N1200 Z1.4538064
N1210 ;Departure Move
N1220 G0 Z2.1
N1230 X-2.1 Y-.0019108
N1240 ;Approach Move
N1250 Z1.4538064
N1260 ;Engage Move
N1270 G1 Z1.3538064
N1280 X-1.8829413
N1290 X-1.85 Y.2459095
N1300 ;Cutting
N1310 X-1.8300015 Y.36615
N1320 BSPLINE SD=3 X-1.8249937 Y.3858213 PL=0.0
N1330 X-1.7448088 Y.7636433 PL=.026316
N1340 X-1.3503773 Y1.4416025 PL=.473684
N1350 X-.6481162 Y1.7909367 PL=.473684
N1360 X-.2658658 Y1.846287 PL=.026316
N1370 X-.2459095 Y1.85 PL=0.0
N1380 ;Retract Move
N1390 G1 X.0019107 Y1.8829413
N1400 Y2.1
N1410 Z1.4538064
N1420 ;Departure Move
N1430 G0 Z2.1
N1440 X1.2003965
N1450 ;Approach Move
N1460 Z1.4538064
N1470 ;Engage Move
N1480 G1 Z1.3538064</i></pre>
<br />
This correspondence is trivial:<br />
<br />
<pre>GOTO/-2.1000,1.2004,2.1000,0.0000000,0.0000000,1.0000000</pre>
<br />
<pre><i>N500 G0 C0.0 A0.0
N510 G0 X-2.1 Y1.2003965 Z2.1 S0 D0 M3</i></pre>
<br />
NX CAM specifies X,Y,Z,A3,B3,C3, where A3, B3, and C3 are tool orientation unit vector components. The NX post processor outputted A and C axis angles in degrees, but that's shit. Our machine understands unit vector orientation just fine. Fortunately, we don't have to worry any more about that, because this toolpath is prismatic. We'll deal with simultaneous five axis NURBS toolpaths some other time. NX doesn't seem to want to generate such things, anyway.<br />
<br />
Moving on:<br />
<br />
<pre>GOTO/-1.7710,1.5994,1.3538
NURBS/
KNOT/1.0000000
CNTRL/-1.6893,1.6898,1.3538
CNTRL/-1.6017,1.7730,1.3538
CNTRL/-1.5072,1.8500,1.3538</pre>
<br />
<pre><i>N580 X-1.7709655 Y1.5993672
N590 BSPLINE SD=3 X-1.6892636 Y1.6898064 PL=0.0
N600 X-1.601724 Y1.7730024 PL=1.
N610 X-1.5072473 Y1.85 PL=0.0</i></pre>
<br />
"It's a NURBS! Look out, sir! ARRRRGGGG!!!" No worries, I got this for ya. So, we see some shit going on. KNOT/1.0 clearly means something, but I'm not seeing it represented in our NC, unless it's that PL=1 term. Could be. And then there's those PL=0s. And the SD=3. Either these things are implicit, or our listing is woefully incomplete and will not serve our needs. I can believe that SD3 is implicit - sure, we're always working with cubic NURBS.<br />
<br />
Unfortunately, we haven't yet made enough ill-gotten assumptions to fully misunderstand the situation. Let's extrapolate more.<br />
<br />
<pre>NURBS/
KNOT/0.0625000,0.3125000,0.4375000,0.5625000,0.8125000,0.9375000,1.0000000
CNTRL/-1.7716,1.1745,1.3538
CNTRL/-1.7126,1.2629,1.3538
CNTRL/-1.6205,1.3801,1.3538
CNTRL/-1.5040,1.5040,1.3538
CNTRL/-1.3801,1.6205,1.3538
CNTRL/-1.2462,1.7258,1.3538
CNTRL/-1.1212,1.8066,1.3538
CNTRL/-1.0662,1.8389,1.3538
CNTRL/-1.0481,1.8500,1.3538</pre>
<br />
<pre><i>N910 BSPLINE SD=3 X-1.7715783 Y1.1745064 PL=0.0
N920 X-1.7126259 Y1.2629285 PL=.0625
N930 X-1.6205476 Y1.3801208 PL=.25
N940 X-1.5039659 Y1.5039613 PL=.125
N950 X-1.3800976 Y1.620521 PL=.125
N960 X-1.2462019 Y1.7258162 PL=.25
N970 X-1.1212275 Y1.8066001 PL=.125
N980 X-1.0662174 Y1.838871 PL=.0625
N990 X-1.0481092 Y1.85 PL=0.0</i></pre>
<br />
There's definitely a relationship between KNOT and PL values. Our KNOTs are<br />
[0.0625, 0.3125, 0.4375, 0.5625, 0.8125, 0.9375, 1.0] and our PLs are<br />
[0.0, 0.0625, 0.25, 0.125, 0.125, 0.25, 0.125, 0.0625, 0.0]. Let's prepend a 0 and append a 1 to our KNOTs, giving<br />
[0, 0.0625, 0.3125, 0.4375, 0.5625, 0.8125, 0.9375, 1.0, 1]. In Python list generator syntax, [KNOTs[n]-KNOTs[n-1] for n in range(1,len(PLs))] produces<br />
[0.0625, 0.25, 0.125, 0.125, 0.25, 0.125, 0.0625, 0.0]. These happen to be our PL values.<br />
<br />
And that's that. The next step for me is to encode all of these assumptions into a Python script that takes a path listing as input and outputs 840D NC. I will do so <a href="https://github.com/erikhvatum/TetraDecaPost/blob/master/dmu65ul_post.py">here</a>.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-72182276651039528612017-03-08T20:49:00.000+01:002017-03-08T20:49:41.771+01:00QML expression binds as C++ operator overloads... without QMLIt's nice that QML permits binding expressions, such as field_Y = 2 * slider_X. It's not nice that JavaScript is involved. It's not nice that these binds are uni-directional.<br />
<br />
Let's solve both of these dumbshit millennial JavaScript fucktard problems, which originate in the extremely endearing habit of kids rejecting the wisdom of their elders in favor of the scrpting flavor of the nanosecond. Good intentions and all that.<br />
<br />
C++ operator overloading facilitates creation of any domain specific language you like, such as formal EBNF LL parser and interpreter specification, and these are compiled down to fast code using the three hundred decillion man-hours of PHd CS wizardry invested in whichever optimizing compiler you happen to be using.<br />
<br />
Representing data bind expressions is no kind of challenge at all. However, all other people are idiots, leaving it to me to implement this, and I'm rather over-committed. So, we'll see.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-68887664830606652602017-01-14T21:16:00.000+01:002017-01-14T21:16:17.861+01:00The expression is invalid for update in NX. Foo^2: Dimension error<div class="separator" style="clear: both; text-align: left;">
If jump into Siemens NX, you'll soon run into the following error, prompted by your attempt to include a <i>t squared</i> term:</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNx1PqUhW2e9_lDiUAaxMrzGDVKK2MpmWBx-TIs6IYZjrPD2h8g77IEYsX61KKaXlQFPei66ht0_As_RG87OmbRhDCscy-U2aFNlLYlvVXXCjlBCs6nkScBANTQFbrFuvrtMOWAum7WQ/s1600/the_expression_is_invalid_for_update_in_NX_dimension_error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNx1PqUhW2e9_lDiUAaxMrzGDVKK2MpmWBx-TIs6IYZjrPD2h8g77IEYsX61KKaXlQFPei66ht0_As_RG87OmbRhDCscy-U2aFNlLYlvVXXCjlBCs6nkScBANTQFbrFuvrtMOWAum7WQ/s1600/the_expression_is_invalid_for_update_in_NX_dimension_error.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The expression is invalid for update in NX. yt: Dimension error.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Coercing t^2 into inch units does not seem to work:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFHnytBOX4-r_BGe77g-hiFjOwe4hZB5WHDUPXiYcA5Ws9JKZk0uzHF2BbBcR_djaTFgIMncSQFlTW5sQOIUE5iosoE4uPe6IpQnxwSn6VSeLiAetuo8eZtKxMFoK1JcUeb-fRZzmSlA/s1600/the_expression_is_invalid_for_update_in_NX_syntax_error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFHnytBOX4-r_BGe77g-hiFjOwe4hZB5WHDUPXiYcA5Ws9JKZk0uzHF2BbBcR_djaTFgIMncSQFlTW5sQOIUE5iosoE4uPe6IpQnxwSn6VSeLiAetuo8eZtKxMFoK1JcUeb-fRZzmSlA/s1600/the_expression_is_invalid_for_update_in_NX_syntax_error.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The solution is to make a unitless expression, a "constant", that is used in place of <i>t:</i></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT5waS979_W_XACbfHf4FO691JJuIwpe7PcRRAReDzEO5Q7PSQIG3AZexFh1c1i2C4uzHUmEmueE9odw1dr1DD_IU4LCQdVVHRl5gsa0NzdqbR2eIVJFcKwEo0CBk70jTjAONoVnUVlA/s1600/the_expression_is_valid_for_update_in_NX_no_error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT5waS979_W_XACbfHf4FO691JJuIwpe7PcRRAReDzEO5Q7PSQIG3AZexFh1c1i2C4uzHUmEmueE9odw1dr1DD_IU4LCQdVVHRl5gsa0NzdqbR2eIVJFcKwEo0CBk70jTjAONoVnUVlA/s1600/the_expression_is_valid_for_update_in_NX_no_error.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<i><br /></i></div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-35810053252825982492016-08-27T01:20:00.001+02:002016-08-27T02:17:26.915+02:00Lazily Exposing an std::vector to Python as a Numpy Array with pybind11Suppose one wishes to expose to Python multi-threaded C++ code that generates output in the form of flat integer or floating point value arrays, and these arrays should appear as Numpy arrays in Python. The two common approaches are (replacing "element" with <span style="color: blue; font-family: "courier new" , "courier" , monospace;">bool</span>, <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::uint16_t</span>, <span style="color: blue; font-family: "courier new" , "courier" , monospace;">int</span>, <span style="color: blue; font-family: "courier new" , "courier" , monospace;">float</span>, <span style="color: blue; font-family: "courier new" , "courier" , monospace;">double</span>, etc):<br />
<br />
<ul>
<li>Copying the contents of whatever C++ produces, whether <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::vector<element></span> or <span style="color: blue; font-family: "courier new" , "courier" , monospace;">element*</span> with length parameter, into Numpy arrays.</li>
<li>Modifying the C++ code so that it accepts pre-allocated data storage in the form of element* with length parameter, and using the Numpy C API or array.ctypes API to feed the pointer to C++. This avoids a copy operation.</li>
</ul>
<div>
With <a href="https://github.com/pybind/pybind11">pybind11</a>, there is a better way: 1) keep any <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::vector<></span> that may be exposed to Python in an <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr<std::vector></span>, 2) expose the concrete <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::vector<element></span> types used with <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr<std::vector<>></span> as the associated "holder" type for each, with an appropriate <span style="color: blue; font-family: "courier new" , "courier" , monospace;">.def_buffer</span> call, 3) and in response to requests from Python, lazily retrieve (causing instantiation of) the Python object wrapping the vector requested, feed this to Numpy, and cache and return the resulting Numpy array.</div>
<div>
<br /></div>
<div>
This arrangement may sound complicated, but it is, by far, the most natural and flexible of all approaches: without resort to Python reference counting or requirement to acquire the GIL, a vector exposed in this manner is not garbage collected until both the last outstanding Python reference and the last outstanding C++ reference are gone. This is awesome.</div>
<div>
<br /></div>
<div>
Let's break down the rather dense instructions presented above.</div>
<div>
<br /></div>
<h2>
1</h2>
<div>
Keep any <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::vector<></span> that may be exposed to Python in an <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr<std::vector<>></span>.<br />
<br />
There not much to this. <span style="color: blue; font-family: "courier new" , "courier" , monospace;">struct Foo { std::vector<int> v; };</span> changes to <span style="color: blue; font-family: "courier new" , "courier" , monospace;">Foo { std::shared_ptr<std::vector<int>> v; };</span>, and any <span style="color: blue; font-family: "courier new" , "courier" , monospace;">v.</span> changes to <span style="color: blue; font-family: "courier new" , "courier" , monospace;">v-></span></div>
<h2>
2</h2>
<div>
Expose the concrete <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::vector<element></span> types used with <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr<std::vector<>> </std::vector></span>as the associated "holder" type for each, with an appropriate <span style="color: blue; font-family: "courier new" , "courier" , monospace;">.def_buffer</span> call.</div>
<div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">py::class_<std::vector<std::uint64_t>, std::shared_ptr<std::vector<std::uint64_t>>>(m, "_HistogramBuffer")</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> .def_buffer([](std::vector<std::uint64_t>& v) {</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return py::buffer_info(</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> v.data(),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> sizeof(std::uint64_t),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> py::format_descriptor<std::uint64_t>::format(),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 1,</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> { v.size() },</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> { sizeof(std::uint64_t) });</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> });</span></div>
</div>
<h2>
3</h2>
<div>
In response to requests from Python, lazily retrieve (causing instantiation of) the Python object wrapping the vector requested, feed this to Numpy, and cache and return the resulting Numpy array. The lines of code where this is done are in bold; the rest is provided as minimal context, so that you have some chance of figuring out what I'm talking about :)</div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">template<typename T></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">struct StatsBase</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> static void expose_via_pybind11(py::module& m);</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> StatsBase();</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> StatsBase(const StatsBase&) = delete;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> StatsBase& operator = (const StatsBase&) = delete;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> virtual ~StatsBase() = default;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> std::tuple<T, T> extrema;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> std::size_t max_bin;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> std::shared_ptr<std::vector<std::uint64_t>> histogram;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // A numpy array that is a read-only view of histogram. Lazily created in response to get_histogram_py calls.</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> std::shared_ptr<py::object> histogram_py;</py::object></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> py::object& get_histogram_py();</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">};</span></div>
</div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">template<typename T></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">void StatsBase<T>::expose_via_pybind11(py::module& m)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> std::string s = std::string("_StatsBase_") + component_type_names[std::type_index(typeid(T))];</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> py::class_<StatsBase<T>, std::shared_ptr<StatsBase<T>>>(m, s.c_str())</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> .def_readonly("extrema", &StatsBase<T>::extrema)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> .def_readonly("max_bin", &StatsBase<T>::max_bin)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> .def_readonly("histogram_buff", &StatsBase<T>::histogram)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> .def_property_readonly("histogram", [](StatsBase<T>& v){return v.get_histogram_py();});</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">template<typename T></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">StatsBase<T>::StatsBase()</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> : extrema(0, 0),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> max_bin(0),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> histogram(new std::vector<std::uint64_t>(bin_count<T>(), 0)),</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> histogram_py(nullptr)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">template<typename T></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">py::object& StatsBase<T>::get_histogram_py()</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(!histogram_py)</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> {</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> <b>py::object buffer_obj = py::cast(histogram);</b></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> histogram_py.reset(new py::object(PyArray_FromAny(buffer_obj.ptr(), nullptr, 1, 1, 0, nullptr), false), &safe_py_deleter</b></span><b style="color: blue; font-family: "Courier New", Courier, monospace; font-size: small;">);</b></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return *histogram_py;</span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
</div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;">StatsBase<T>::get_histogram_py()</span> is a bit complex; let's break it down:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;">if(!histogram_py)</span></div>
</div>
<div>
If the <span style="color: blue; font-family: "courier new" , "courier" , monospace;">StatsBase<T></span> instance in question does not already have a non-null <span style="color: blue; font-family: "courier new" , "courier" , monospace;">histogram_py</span> pointer...</div>
<div>
<br /></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;">py::object buffer_obj = py::cast(histogram);</span></div>
<div>
Get a Python object wrapping our <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr<std::vector<std::uint64_t>></span> instance. This wrapper will be as we specified to pybind11 and will therefore have a buffer protocol interface understood by Numpy.</div>
<div>
<b><br /></b></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;">histogram_py.reset(new py::object(PyArray_FromAny(buffer_obj.ptr(), nullptr, 1, 1, 0, nullptr), false), &safe_py_deleter</span><span style="color: blue; font-family: "courier new" , "courier" , monospace;">);</span></div>
<div>
Use the <span style="color: blue; font-family: "courier new" , "courier" , monospace;">PyArray_FromAny</span> call to make a Numpy array that is a view of our vector and keep the resulting <span style="color: blue; font-family: "courier new" , "courier" , monospace;">PyObject*</span> in a pybind11 <span style="color: blue; font-family: "courier new" , "courier" , monospace;">PyObject*</span> wrapper that will decrement its refcount appropriately when destroyed. Store this in an <span style="color: blue; font-family: "courier new" , "courier" , monospace;">std::shared_ptr</span> with a GIL-safe deleter in order to avoid crashing in the case where a C++ background thread is the last thing with a reference to a <span style="color: blue; font-family: "courier new" , "courier" , monospace;">StatsBase</span> instance that has been accessed from a no-longer-extant Python reference.</div>
<div>
<br /></div>
<div>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;">return *histogram_py;</span></div>
<div>
Return a C++ reference to the py::object representing the Numpy array.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
This example is from <a href="https://github.com/erikhvatum/RisWidget/tree/master/ris_widget/ndimage_statistics">real world code</a> (it may be necessary to look in the new_ndimage_statistics branch, but I expect to merge this into master within the next few days). Apologies for not making a minimal example. If you'd like one or have any questions, please ask!</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-62217023456817799202016-08-24T00:39:00.001+02:002016-08-24T00:39:28.227+02:00BTRFS Is a God Damned JokeI tried storing an 8GiB virtual box disk image on BTRFS. Well, it copied over successfully, but minutes into 'pacman -Syu', the Linux instance in the VM began reporting copious IDE errors. Suspecting BTRFS copy-on-write being an issue, I moved the disk image back to a ZFS volume. This took inordinately long - it definitely was a COW issue. BTRFS went absolutely crazy as the VM wrote here, there and everywhere to its virtual disk, requiring a <i>competent</i> copy-on-write implementation - which BTRFS <i>does not have</i>.<br />
<br />
That VM, again on ZFS, is again working flawlessly. ZFS is a copy-on-write filesystem and <b>works</b>. BTRFS is a copy-on-write filesystem and <b>does not work</b>.<br />
<br />
We're how many years into BTRFS being officially "stable"? And it blows chunks the instant you attempt to, say, modify a file a lot? That doesn't seem right. Perhaps I'm the only one, and I'm doing something wrong? Nope. <a href="https://blog.pgaddict.com/posts/friends-dont-let-friends-use-btrfs-for-oltp">BTRFS just plain sucks</a>.<br />
<br />
The thing I did wrong with BTRFS was using BTRFS. Apparently, I could <i>disable</i> BTRFS's copy-on-write support for my VM disk image files. But, then my VM disk image files would have no FS-level data checksums or snapshot capability. If that's what I wanted, I'd keep my VM images on XFS or EXT4. It's not, and BTRFS is apparently little better than EXT4 with some additional features that <i>don't work</i>, so ZFS it is.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-37989247729087026252016-06-10T03:59:00.002+02:002016-06-10T03:59:55.746+02:00blitTextureForWidget: Yeah, Why Don't You?I made <a href="https://github.com/erikhvatum/multiple_gl_viewport_fps_toy">this little test application</a> in order to explore the impact of swap interval upon multiple visible QOpenGLWidget instances belonging to the same process. It provided yeoman service, facilitating a massive FPS increase in <a href="https://github.com/erikhvatum/RisWidget">important production code</a> by demonstrating that swap interval 1, while friendly and well intended, really held us back. Alas, even with this issue beheaded, something is yet rotten in the state of our OpenGL contexts:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi016ME_L1a_JUdtdL98AfzA2iNm1IDPSJu0wW0vil34VFwsBAWmpUuzmSjDshp4vZ8wi80qfnc2Uy6o5a2Qupy6J_eNUFnymTyCBL9OBa47aF5w2OHzNjbix-wiaQyviqtG6RnDsKEMA/s1600/Screenshot_20160609_155043.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi016ME_L1a_JUdtdL98AfzA2iNm1IDPSJu0wW0vil34VFwsBAWmpUuzmSjDshp4vZ8wi80qfnc2Uy6o5a2Qupy6J_eNUFnymTyCBL9OBa47aF5w2OHzNjbix-wiaQyviqtG6RnDsKEMA/s1600/Screenshot_20160609_155043.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwpX50G2bUGcboXUM2cj8usCahNLA09NXFrDsWiGi3aPaw5B2CyqIz3AAtGGnXuu1v14mQ9Elqsqv-TCQB8CFZ05kqBlis-5fV0ho8979EFw6YVFdPLB7aVCoTYKD6im9k0YRY_v_5Bw/s1600/Screenshot_20160609_155150.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwpX50G2bUGcboXUM2cj8usCahNLA09NXFrDsWiGi3aPaw5B2CyqIz3AAtGGnXuu1v14mQ9Elqsqv-TCQB8CFZ05kqBlis-5fV0ho8979EFw6YVFdPLB7aVCoTYKD6im9k0YRY_v_5Bw/s1600/Screenshot_20160609_155150.png" /></a></div>
<br />
Making the plain (non-OpenGL) dock widget floating instead of docked increases FPS by <b><span style="font-size: x-large;">146%</span></b>.<br />
<br />
QPlatformBackingStore::composeAndFlush(..) is the cause:<br />
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QPlatformBackingStore</span><span style="color: black;">::</span><span style="color: black; font-style: italic;">composeAndFlush</span><span style="color: black;">(</span><span style="color: purple;">QWindow</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">window</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRegion</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">region</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QPoint</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">offset</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QPlatformTextureList</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">textures</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">context</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">translucentBackground</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span>qt_window_private<span style="color: black;">(</span><span style="color: black;">window</span><span style="color: black;">)-></span>receivedExpose<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">context</span><span style="color: black;">-></span><span style="color: black;">makeCurrent</span><span style="color: black;">(</span><span style="color: black;">window</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: navy;">qWarning</span><span style="color: black;">(</span><span style="color: green;">"composeAndFlush:</span><span style="color: silver;"> </span><span style="color: green;">makeCurrent()</span><span style="color: silver;"> </span><span style="color: green;">failed"</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QWindowPrivate</span><span style="color: black;">::</span>get<span style="color: black;">(</span><span style="color: black;">window</span><span style="color: black;">)-></span>lastComposeTime<span style="color: black;">.</span>start<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">context</span><span style="color: black;">-></span><span style="color: black;">functions</span><span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glViewport</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">-></span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">-></span><span style="color: black;">devicePixelRatio</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">-></span><span style="color: black;">height</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">-></span><span style="color: black;">devicePixelRatio</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glClearColor</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">translucentBackground</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glClear</span><span style="color: black;">(</span><span style="color: navy;">GL_COLOR_BUFFER_BIT</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>create<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>bind<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: silver;"> </span><span style="color: black;">deviceWindowRect</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">deviceRect</span><span style="color: black;">(</span><span style="color: purple;">QRect</span><span style="color: black;">(</span><span style="color: purple;">QPoint</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">-></span><span style="color: black; font-style: italic;">size</span><span style="color: black;">()),</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Textures</span><span style="color: silver;"> </span><span style="color: green;">for</span><span style="color: silver;"> </span><span style="color: green;">renderToTexture</span><span style="color: silver;"> </span><span style="color: green;">widgets.</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: silver;"> </span><span style="color: black;"><</span><span style="color: silver;"> </span><span style="color: black;">textures</span><span style="color: black;">-></span><span style="color: black;">count</span><span style="color: black;">();</span><span style="color: silver;"> </span><span style="color: black;">++</span><span style="color: black;">i</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">textures</span><span style="color: black;">-></span><span style="color: black;">flags</span><span style="color: black;">(</span><span style="color: black;">i</span><span style="color: black;">).</span><span style="color: black;">testFlag</span><span style="color: black;">(</span><span style="color: purple;">QPlatformTextureList</span><span style="color: black;">::</span><span style="color: purple;">StacksOnTop</span><span style="color: black;">))</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: green;">/*1*/</span><span style="color: silver;"> </span><span style="color: black;">blitTextureForWidget</span><span style="color: black;">(</span><span style="color: black;">textures</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">deviceWindowRect</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">offset</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Backingstore</span><span style="color: silver;"> </span><span style="color: green;">texture</span><span style="color: silver;"> </span><span style="color: green;">with</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">normal</span><span style="color: silver;"> </span><span style="color: green;">widgets.</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">GLuint</span><span style="color: silver;"> </span><span style="color: black;">textureId</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">::</span>Origin<span style="color: silver;"> </span><span style="color: black;">origin</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">::</span>OriginTopLeft<span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: purple;">QPlatformGraphicsBuffer</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">graphicsBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">this</span><span style="color: black;">-></span><span style="color: black; font-style: italic;">graphicsBuffer</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span>size<span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glDeleteTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glGenTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBindTexture</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">ctx</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">isOpenGLES</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">format</span><span style="color: black;">().</span><span style="color: black;">majorVersion</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">>=</span><span style="color: silver;"> </span><span style="color: navy;">3</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameteri</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_BASE_LEVEL</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameteri</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_MAX_LEVEL</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameterf</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_MIN_FILTER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_NEAREST</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameterf</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_MAG_FILTER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_NEAREST</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameterf</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_WRAP_S</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_CLAMP_TO_EDGE</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexParameterf</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_TEXTURE_WRAP_T</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_CLAMP_TO_EDGE</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span>QPlatformGraphicsBufferHelper<span style="color: black;">::</span>lockAndBindToTexture<span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">needsSwizzle</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">premultiplied</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span>size<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: navy;">0</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span>unlock<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">region</span><span style="color: black;">.</span><span style="color: black;">isEmpty</span><span style="color: black;">()){</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBindTexture</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: green;">/*2*/</span><span style="color: silver;"> </span>QPlatformGraphicsBufferHelper<span style="color: black;">::</span>lockAndBindToTexture<span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">needsSwizzle</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">premultiplied</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span>origin<span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: purple;">QPlatformGraphicsBuffer</span><span style="color: black;">::</span>OriginBottomLeft<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">origin</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">::</span>OriginBottomLeft<span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">textureId</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureId</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">TextureFlags</span><span style="color: silver;"> </span><span style="color: black;">flags</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">textureId</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">toTexture</span><span style="color: black;">(</span><span style="color: black;">deviceRegion</span><span style="color: black;">(</span><span style="color: black;">region</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">offset</span><span style="color: black;">),</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">flags</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">needsSwizzle</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">flags</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">TextureSwizzle</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">flags</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">TexturePremultiplied</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">flags</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">TextureFlip</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">origin</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">::</span>OriginBottomLeft<span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glEnable</span><span style="color: black;">(</span><span style="color: navy;">GL_BLEND</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">premultiplied</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBlendFuncSeparate</span><span style="color: black;">(</span><span style="color: navy;">GL_ONE</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE_MINUS_SRC_ALPHA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">else</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBlendFuncSeparate</span><span style="color: black;">(</span><span style="color: navy;">GL_SRC_ALPHA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE_MINUS_SRC_ALPHA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_ONE</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">textureId</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">needsSwizzle</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>setSwizzleRB<span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">The</span><span style="color: silver;"> </span><span style="color: green;">backingstore</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">for</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">entire</span><span style="color: silver;"> </span><span style="color: green;">tlw.</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">In</span><span style="color: silver;"> </span><span style="color: green;">case</span><span style="color: silver;"> </span><span style="color: green;">of</span><span style="color: silver;"> </span><span style="color: green;">native</span><span style="color: silver;"> </span><span style="color: green;">children</span><span style="color: silver;"> </span><span style="color: green;">offset</span><span style="color: silver;"> </span><span style="color: green;">tells</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">position</span><span style="color: silver;"> </span><span style="color: green;">relative</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">tlw.</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: silver;"> </span><span style="color: black;">srcRect</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">toBottomLeftRect</span><span style="color: black;">(</span><span style="color: black;">deviceWindowRect</span><span style="color: black;">.</span><span style="color: black;">translated</span><span style="color: black;">(</span><span style="color: black;">offset</span><span style="color: black;">),</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QMatrix3x3</span><span style="color: silver;"> </span><span style="color: black;">source</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>QOpenGLTextureBlitter<span style="color: black;">::</span>sourceTransform<span style="color: black;">(</span><span style="color: black;">srcRect</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">textureSize</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">origin</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>blit<span style="color: black;">(</span><span style="color: black;">textureId</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: purple;">QMatrix4x4</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">source</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">needsSwizzle</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>setSwizzleRB<span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Textures</span><span style="color: silver;"> </span><span style="color: green;">for</span><span style="color: silver;"> </span><span style="color: green;">renderToTexture</span><span style="color: silver;"> </span><span style="color: green;">widgets</span><span style="color: silver;"> </span><span style="color: green;">that</span><span style="color: silver;"> </span><span style="color: green;">have</span><span style="color: silver;"> </span><span style="color: green;">WA_AlwaysStackOnTop</span><span style="color: silver;"> </span><span style="color: green;">set.</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: silver;"> </span><span style="color: black;"><</span><span style="color: silver;"> </span><span style="color: black;">textures</span><span style="color: black;">-></span><span style="color: black;">count</span><span style="color: black;">();</span><span style="color: silver;"> </span><span style="color: black;">++</span><span style="color: black;">i</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">textures</span><span style="color: black;">-></span><span style="color: black;">flags</span><span style="color: black;">(</span><span style="color: black;">i</span><span style="color: black;">).</span><span style="color: black;">testFlag</span><span style="color: black;">(</span><span style="color: purple;">QPlatformTextureList</span><span style="color: black;">::</span><span style="color: purple;">StacksOnTop</span><span style="color: black;">))</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">blitTextureForWidget</span><span style="color: black;">(</span><span style="color: black;">textures</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">i</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">window</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">deviceWindowRect</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">offset</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glDisable</span><span style="color: black;">(</span><span style="color: navy;">GL_BLEND</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: maroon;">d_ptr</span><span style="color: black;">-></span><span style="color: maroon;">blitter</span><span style="color: black;">-></span>release<span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">context</span><span style="color: black;">-></span><span style="color: black;">swapBuffers</span><span style="color: black;">(</span><span style="color: black;">window</span><span style="color: black;">);</span></pre>
<br />
<pre>}<!--EndFragment--></pre>
<br />
The line marked with /*1*/ is fast to execute. The line marked with /*2*/ is very slow.<br />
<br />
/*1*/ is called for our docked QOpenGLWidgets. /*2*/ is called for our docked QWidget that does not contain a QOpenGLWidget, but it is not called when that QWidget is made floating rather than docked.<br />
<br />
/*2*/ ends up calling QPlatformGraphicsBufferHelper::bindSWToTexture(..):<br />
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: purple;">QPlatformGraphicsBufferHelper</span><span style="color: black;">::</span><span style="color: black;">bindSWToTexture</span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QPlatformGraphicsBuffer</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">swizzleRandB</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">premultipliedB</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">subRect</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_OPENGL</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">ctx</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">ctx</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black;">isLocked</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">QPlatformGraphicsBuffer</span><span style="color: black;">::</span><span style="color: purple;">SWReadAccess</span><span style="color: black;">))</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black;">size</span><span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: navy;">Q_ASSERT</span><span style="color: black;">(</span><span style="color: black;">subRect</span><span style="color: black;">.</span><span style="color: black;">isEmpty</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: black;">(</span><span style="color: purple;">QPoint</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: navy;">0</span><span style="color: black;">),</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">).</span><span style="color: black;">contains</span><span style="color: black;">(</span><span style="color: black;">subRect</span><span style="color: black;">));</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">GLuint</span><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_BYTE</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">needsConversion</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">swizzle</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format</span><span style="color: silver;"> </span><span style="color: black;">imageformat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: black;">toImageFormat</span><span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black;">format</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black; font-style: italic;">data</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black; font-style: italic;">bytesPerLine</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">imageformat</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">graphicsBuffer</span><span style="color: black;">-></span><span style="color: black; font-style: italic;">bytesPerLine</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">needsConversion</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">switch</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">imageformat</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_ARGB32_Premultiplied</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">no</span><span style="color: silver;"> </span><span style="color: green;">break</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGB32</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_ARGB32</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">swizzle</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGBA8888_Premultiplied</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">no</span><span style="color: silver;"> </span><span style="color: green;">break</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGBX8888</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGBA8888</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_BGR30</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_A2BGR30_Premultiplied</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">isOpenGLES</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">format</span><span style="color: black;">().</span><span style="color: black;">majorVersion</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">>=</span><span style="color: silver;"> </span><span style="color: navy;">3</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_INT_2_10_10_10_REV</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB10_A2</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">needsConversion</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGB30</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_A2RGB30_Premultiplied</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">isOpenGLES</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">format</span><span style="color: black;">().</span><span style="color: black;">majorVersion</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">>=</span><span style="color: silver;"> </span><span style="color: navy;">3</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_INT_2_10_10_10_REV</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB10_A2</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span>swiz5zle<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">needsConversion</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">default</span><span style="color: black;">:</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">needsConversion</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">needsConversion</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">convertToFormat</span><span style="color: black;">(</span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGBA8888</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">functions</span><span style="color: black;">();</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">subRect</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">isNull</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: black;">(</span><span style="color: purple;">QPoint</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: navy;">0</span><span style="color: black;">),</span><span style="color: black;">size</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexImage2D</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">constBits</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: navy;">#ifndef</span><span style="color: silver;"> </span>QT_OPENGL_ES_2</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">ctx</span><span style="color: black;">-></span><span style="color: black;">isOpenGLES</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glPixelStorei</span><span style="color: black;">(</span><span style="color: navy;">GL_UNPACK_ROW_LENGTH</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexSubImage2D</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">x</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">y</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">constScanLine</span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">y</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">+</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">x</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glPixelStorei</span><span style="color: black;">(</span><span style="color: navy;">GL_UNPACK_ROW_LENGTH</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: navy;">#endif</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">if</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">rect</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">wide</span><span style="color: silver;"> </span><span style="color: green;">enough</span><span style="color: silver;"> </span><span style="color: green;">it's</span><span style="color: silver;"> </span><span style="color: green;">cheaper</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">just</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">extend</span><span style="color: silver;"> </span><span style="color: green;">it</span><span style="color: silver;"> </span><span style="color: green;">instead</span><span style="color: silver;"> </span><span style="color: green;">of</span><span style="color: silver;"> </span><span style="color: green;">doing</span><span style="color: silver;"> </span><span style="color: green;">an</span><span style="color: silver;"> </span><span style="color: green;">image</span><span style="color: silver;"> </span><span style="color: green;">copy</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">>=</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">/</span><span style="color: silver;"> </span><span style="color: navy;">2</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">setX</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">);</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">setWidth</span><span style="color: black;">(</span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">if</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">sub-rect</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">full-width</span><span style="color: silver;"> </span><span style="color: green;">we</span><span style="color: silver;"> </span><span style="color: green;">can</span><span style="color: silver;"> </span><span style="color: green;">pass</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">image</span><span style="color: silver;"> </span><span style="color: green;">data</span><span style="color: silver;"> </span><span style="color: green;">directly</span><span style="color: silver;"> </span><span style="color: green;">to</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">OpenGL</span><span style="color: silver;"> </span><span style="color: green;">instead</span><span style="color: silver;"> </span><span style="color: green;">of</span><span style="color: silver;"> </span><span style="color: green;">copying,</span><span style="color: silver;"> </span><span style="color: green;">since</span><span style="color: silver;"> </span><span style="color: green;">there's</span><span style="color: silver;"> </span><span style="color: green;">no</span><span style="color: silver;"> </span><span style="color: green;">gap</span><span style="color: silver;"> </span><span style="color: green;">between</span><span style="color: silver;"> </span><span style="color: green;">scanlines</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexSubImage2D</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">y</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">constScanLine</span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">y</span><span style="color: black;">()));</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexSubImage2D</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">x</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">y</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: black;">rect</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">pixelType</span><span style="color: black;">,</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">copy</span><span style="color: black;">(</span><span style="color: black;">rect</span><span style="color: black;">).</span><span style="color: black;">constBits</span><span style="color: black;">());</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">}</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">swizzleRandB</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">swizzleRandB</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">swizzle</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">premultipliedB</span><span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">premultipliedB</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">premultiplied</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
</pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: navy;">#else</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">Q_UNUSED</span><span style="color: black;">(</span>graphicsBuffer<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">Q_UNUSED</span><span style="color: black;">(</span>swizzleRandB<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">Q_UNUSED</span><span style="color: black;">(</span>premultipliedB<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: purple;">Q_UNUSED</span><span style="color: black;">(</span>subRect<span style="color: black;">)</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: navy;">#endif</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">QT_NO_OPENGL</span></pre>
<br />
<pre>}<!--EndFragment--></pre>
<br />
Those glTexSubImage2D calls are blocking texture uploads executed in the main thread (theoretically, glTexSubImage2D should be non-blocking, but profiling this code makes it very apparent that glTexSubImage2D is blocking). In a profiler, it is easily seen that the huge FPS hit is mostly the result of <i>synchronization delay</i>; it takes time to marshal data to the GPU, and most of that time is spent waiting for inherently asynchronous things, such as DMA transfers, to most certainly be definitely completed, beyond a shadow of a doubt, triply confirmed, with extra delays just to be super-ultra-incredibly-sure. If a modern video game were to upload its textures like this, one-at-a-time, in a blocking fashion, you would be lucky to get one frame per minute.<br />
<br />
Perhaps we can engage the code path used for QGraphicsProxyWidgets and render QWidgets directly to a pixel buffer? I don't know if QGraphicsProxyWidget actually does this, but the FPS hit from placing a QWidget updated every frame in a QGraphicsScene with an OpenGL viewport is less severe than the hit from docking a plain QWidget updated every frame alongside OpenGL viewports that are updated every frame. One way we might try to do this is by simply making the plain QWidget containing the QLabel a QOpenGLWidget. I think I remember hearing that QWidget children of QOpenGLWidgets are rendered properly, within the QOpenGLWidget viewport. Perhaps this is the ticket.<br />
<br />
<span style="font-family: monospace;"><span style="background-color: white; color: #ff5454; font-weight: bold;">[05:34 PM][</span><span style="background-color: white; color: #5454ff; font-weight: bold;">ehvatum@heavenly:</span><span style="background-color: white; color: #ff54ff; font-weight: bold;">~/multiple_gl_viewport_fps_toy</span><span style="background-color: white; color: #ff5454; font-weight: bold;">]</span><span style="background-color: white; color: #54ff54; font-weight: bold;">></span><span style="background-color: white;"> git diff
</span><br /><span style="background-color: white; font-weight: bold;">diff --git a/MainWindow.cpp b/MainWindow.cpp</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">index fd8ccb5..3e9acf2 100644</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">--- a/MainWindow.cpp</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">+++ b/MainWindow.cpp</span><span style="background-color: white;">
</span><br /><span style="background-color: white; color: #18b2b2;">@@ -6,7 +6,7 @@</span><span style="background-color: white;"> MainWindow::MainWindow(QWidget *parent)
</span><br /> m_central_fps_item(m_central_gs->addText("")),
<br /> m_central_gv(new GL_QGraphicsView(0, m_central_gs)),
<br /> m_central_swap_interval("central swapInterval == 0"),
<br /><span style="background-color: white; color: #b21818;">- m_left_widget(new QWidget()),</span><span style="background-color: white;">
</span><br /><span style="background-color: white; color: #18b218;">+ m_left_widget(new QOpenGLWidget()),</span><span style="background-color: white;">
</span><br /> m_left_dock_widget(new QDockWidget("left widget")),
<br /> m_right_gs(new QGraphicsScene()),
<br /> m_right_fps_item(m_right_gs->addText("")),
<br /><span style="background-color: white; font-weight: bold;">diff --git a/MainWindow.h b/MainWindow.h</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">index 276590c..e14afab 100644</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">--- a/MainWindow.h</span><span style="background-color: white;">
</span><br /><span style="background-color: white; font-weight: bold;">+++ b/MainWindow.h</span><span style="background-color: white;">
</span><br /><span style="background-color: white; color: #18b2b2;">@@ -23,7 +23,7 @@</span><span style="background-color: white;"> protected:
</span><br /> QGraphicsTextItem* m_central_fps_item;
<br /> GL_QGraphicsView* m_central_gv;
<br /> QAction m_central_swap_interval;
<br /><span style="background-color: white; color: #b21818;">- QWidget *m_left_widget;</span><span style="background-color: white;">
</span><br /><span style="background-color: white; color: #18b218;">+ QOpenGLWidget *m_left_widget;</span><span style="background-color: white;">
</span><br /> QLabel *m_left_fps_label;
<br /> QDockWidget* m_left_dock_widget;
<br /> QGraphicsScene* m_right_gs;</span><br />
<br />
With these changes, docking the left widget still imposes the same FPS hit and for the same reason: we wait for an enormous texture upload. Floating the left widget removes the slowdown, unless I resize that floating widget to be the same size as the main window. Together, all of this leads to an insight: the texture uploaded in order to compose a raster surface and a QOpenGLWidget is always the size of the top-level window ultimately containing the widgets.<br />
<br />
So, Qt's raster + QOpenGLWidget composition is completely brain damaged and must be avoided. However, I still need to have QMainWindows containing a mixture of docked QOpenGLWidgets and docked QWidgets. The solution is to use QGLWidgets instead - these do not participate in composition. Doing so brings FPS back to something reasonable.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-15565464199529857072016-06-07T21:38:00.001+02:002016-06-07T21:38:22.106+02:00Python Built With the Latest Intel C Compiler: Why Does jsonifying a Float Fail?! And, Oh Shit, Oh Shit, Oh Shit, What the Fuck, All My Results Are WRONG!<div style="color: #5330e1; font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="color: #c33720; font-variant-ligatures: no-common-ligatures;"><b>[01:57 PM][</b></span><span style="font-variant-ligatures: no-common-ligatures;"><b>zplab@zpl-iscope:</b></span><span style="color: #d53bd3; font-variant-ligatures: no-common-ligatures;"><b>~</b></span><span style="color: #c33720; font-variant-ligatures: no-common-ligatures;"><b>]</b></span><span style="color: #34bd26; font-variant-ligatures: no-common-ligatures;"><b>></b></span><span style="color: black; font-variant-ligatures: no-common-ligatures;"> python</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">Python 3.5.1 (default, May 31 2016, 20:46:24) </span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">[GCC Intel(R) C++ gcc 6.1.1 mode] on linux</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">Type "help", "copyright", "credits" or "license" for more information.</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">>>> 2**39 * 1.596566081047058</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
877721485311.:</div>
<br />
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">>>></span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
So, here we have Python 3.5.1 on Arch, built with the Intel C Compiler, version 16.0.3 20160415. We attempt to multiply two numbers. The result is represented as the string, "877721485311.:".<div>
<br /></div>
<div>
Two problems:</div>
<div>
<ul>
<li>877721485311 is not the correct result.</li>
<li>"877721485311.:" is not a valid string representation of a floating point number. jsonifying this nonsense therefore fails horrendously.</li>
</ul>
<div>
<div style="color: #d53bd3; font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="color: #c33720; font-variant-ligatures: no-common-ligatures;"><b>[01:59 PM][</b></span><span style="color: #5330e1; font-variant-ligatures: no-common-ligatures;"><b>zplab@zpl-iscope:</b></span><span style="font-variant-ligatures: no-common-ligatures;"><b>~/code_repositories</b></span><span style="color: #c33720; font-variant-ligatures: no-common-ligatures;"><b>]</b></span><span style="color: #34bd26; font-variant-ligatures: no-common-ligatures;"><b>></b></span><span style="color: black; font-variant-ligatures: no-common-ligatures;"> python</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">Python 3.5.1 (default, Mar 3 2016, 09:29:07) </span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">[GCC 5.3.0] on linux</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">Type "help", "copyright", "credits" or "license" for more information.</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">>>> 2**39 * 1.596566081047058</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">877721485312.0</span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">>>></span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
Python built with GCC produces correct results; Python built with a super ultra expensive vendor compiler produces bad results. Man, this really takes me back... The last time I dealt with a GCC vs vendor compiler correctness situation on a UNIX-like system was at least 15 years ago, with MIPS Pro, which I had modified to avoid time consuming license checks at each invocation. After restoring the unmodified version and instead cracking the FlexLM license server (yeah, sorry, as a student, I didn't have $16,995.00 to blow on shit that doesn't even fucking work, and cracking software on IRIX was hilariously easy - the license server was such a piece of junk you could use it from the guest account to overwrite any file on the entire system by manipulating the log path environment variable), the issue remained. So, the problem really was MIPS Pro, probably. This time around, in our modern world of bullshit, who even knows or cares? GCC works. Into the trash the Intel Compiler goes...</div>
</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-67914122271201523482016-01-06T02:00:00.003+01:002016-01-19T03:21:25.504+01:00Making PyCharm 5.0.3 and CLion 1.2 run in 30-bit color modeIn 30-bit color mode on Linux, a fresh PyCharm 5.0.3 installation fails to start:<br />
<span style="background-color: white;"><br /></span>
<span style="font-family: monospace;"><span style="background-color: white; color: #ff5454; font-weight: bold;">[06:33 PM][</span><span style="background-color: white; color: #5454ff; font-weight: bold;">ehvatum@heavenly:</span><span style="background-color: white; color: #ff54ff; font-weight: bold;">~/pycharm-community-5.0.2/bin</span><span style="background-color: white; color: #ff5454; font-weight: bold;">]</span><span style="background-color: white; color: #54ff54; font-weight: bold;">></span><span style="background-color: white;"> ./pycharm.sh </span><br />Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=350m; support was removed in 8.0
<br />log4j:WARN No appenders could be found for logger (io.netty.util.internal.logging.InternalLoggerFactory).
<br />log4j:WARN Please initialize the log4j system properly.
<br />log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
<br />[ 571] ERROR - llij.ide.plugins.PluginManager - Unsupported bit depth: 30 <br />sun.java2d.InvalidPipeException: Unsupported bit depth: 30
<br /> at sun.java2d.x11.X11SurfaceData.getSurfaceType(X11SurfaceData.java:611)
<br /> at sun.java2d.x11.X11SurfaceData.getSurfaceType(X11SurfaceData.java:516)
<br /> at sun.awt.X11GraphicsConfig.getSurfaceType(X11GraphicsConfig.java:178)
<br /> at sun.java2d.xr.XRSurfaceData.createData(XRSurfaceData.java:235)
</span><br />
<span style="font-family: monospace;">...</span><br />
<span style="font-family: monospace;"><br /></span>
Workaround: add <span style="font-family: monospace;"><span style="background-color: white;">-Dsun.java2d.opengl=true </span></span>to PyCharm's java call. This can be done by editing pycharm.sh; relevant snippet:<br />
<div>
<br /></div>
<div>
<span style="font-family: monospace;"><span style="background-color: white;"># ---------------------------------------------------------------------
</span><br /># Run the IDE.
<br /># ---------------------------------------------------------------------
<br />LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JAVA_BIN" \
<br /> $AGENT \
<br /> "-Xbootclasspath/a:$IDE_HOME/lib/boot.jar" \
<br /> -classpath "$CLASSPATH" \
<br /> $VM_OPTIONS "-Djb.vmOptionsFile=$vm_options_file" \
<br /> "-XX:ErrorFile=$HOME/java_error_in_PYCHARM_%p.log" \
<br /> -Djb.restart.code=88 -Didea.paths.selector=PyCharm50 \
<br /><span style="background-color: yellow;"><i> -Dsun.java2d.opengl=true \
</i></span><br /> $IDE_PROPERTIES_PROPERTY \
<br /> $IDE_JVM_ARGS \
<br /> com.intellij.idea.Main \
<br /> "$@"</span></div>
<div>
<span style="font-family: monospace;"><br /></span></div>
This trick also works for running CLion in 30-bit mode. It presumably works with the other JetBrains IDEs, though I have not verified this.<br />
<br />
Update: this workaround allows JetBrains IDEs to start in 30-bit mode, but they soon crash due to absolutely idiotic bugs in sun.java2d.opengl. Oh well. I guess I'll just delete all JetBrains stuff, never buy any of their products, and spread the word far and wide that they're basically retarded. Until they fix this - which they never will, because the problem lies in the Oracle Java shit stack. Nonetheless, the fault remains with JetBrains for going with Java. Who could have possibly predicted that would be problematic? Yeah, pretty much anybody.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-7664564770897255182016-01-05T03:18:00.000+01:002016-01-05T07:48:37.749+01:00Arch ZFS root with 4.1.15-1-lts kernel: boot fails with "ZFS: Unable to import root_pool", but "import root_pool" in rescue shell works!On a particular system with heaps of drives and controllers (booting involves 10+ minutes of controller bioses loading, enumerating, scanning, installing, etc), with a ZFS root, the following Arch Linux issue has come, gone, and come again:<br />
<div>
<ul>
<li>The initrd step of booting fails out to a rescue shell with the error, "ZFS: Unable to import pool root_pool".</li>
<li>In that rescue shell, running "zpool import root_pool" succeeds, leading me to wonder why the same thing had apparently just failed.</li>
</ul>
<div>
To get past this error, I've previously banged gongs, chanted in tongues, burned incense, sent postcards to Jesus, and things such as that. However, the issue never quite went away.</div>
<div>
<b><br /></b></div>
<div>
<b>Sigh.</b> What a pain. And so, we arrive at our very last and final reserve strategy: using our brain. Alright, brain. Get to thinking. In the mean time, I'm going to play some video games.</div>
</div>
<div>
<br /></div>
<div>
45 minutes later, our brain says:</div>
<div>
"So, when you later try the thing that failed, the thing that failed then succeeds. Maybe it just fails the first time because it's idiotic and can only ever work when retried, or perhaps the delay itself is the important part? Who cares! Just make it retry once or twice with increasing delays. This is a good plan. Do it. No more thinking is required at this time. Signing off."</div>
<div>
<br /></div>
<div>
Thanks, brain! Let's try that. We boot an Arch image with ZFS integrated from a thumb drive, then run "<span style="font-family: Courier New, Courier, monospace;">zpool import root_pool -R /mnt</span>", and then we "<span style="font-family: Courier New, Courier, monospace;">arch-chroot /mnt</span>". There's this file, <i>/usr/lib/initcpio/hooks/zfs</i>. We edit it (edited portion highlighted and italicized).</div>
<div>
<br /></div>
<div>
<pre style="color: #1f1c1b;"><span style="font-family: Courier New, Courier, monospace;"><span style="background-color: white; color: #0057ae;">ZPOOL_FORCE=</span><span style="background-color: white; color: #bf0303;">""</span><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">ZPOOL_IMPORT_FLAGS=</span><span style="background-color: white; color: #bf0303;">""</span><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">zfs_get_bootfs ()</span><span style="background-color: white;"> </span><b style="background-color: white;">{</b><span style="background-color: white;">
</span><b style="background-color: white;">for</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0095ff;">zfs_dataset</span><span style="background-color: white;"> in </span><span style="background-color: white; color: #0057ae;">$(</span><span style="background-color: white; color: #0095ff;">/usr/bin/zpool</span><span style="background-color: white;"> list -H -o bootfs</span><span style="background-color: white; color: #0057ae;">)</span><b style="background-color: white;">;</b><span style="background-color: white;"> </span><b style="background-color: white;">do</b><span style="background-color: white;">
</span><b style="background-color: white;">case</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">${zfs_dataset}</span><b style="background-color: white;"> in</b><span style="background-color: white;">
</span><span style="background-color: white; color: #bf0303;">""</span><span style="background-color: white;"> </span><b style="background-color: white;">|</b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"-"</span><b style="background-color: white;">)</b><span style="background-color: white;">
</span><span style="background-color: white; color: #898887;"># skip this line/dataset</span><span style="background-color: white;">
</span><b style="background-color: white;">;;</b><span style="background-color: white;">
</span><span style="background-color: white; color: #bf0303;">"no pools available"</span><b style="background-color: white;">)</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">return</span></b><span style="background-color: white;"> 1
</span><b style="background-color: white;">;;</b><span style="background-color: white;">
*</span><b style="background-color: white;">)</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">ZFS_DATASET=${zfs_dataset}</span><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">return</span></b><span style="background-color: white;"> 0
</span><b style="background-color: white;">;;</b><span style="background-color: white;">
</span><b style="background-color: white;">esac</b><span style="background-color: white;">
</span><b style="background-color: white;">done</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">return</span></b><span style="background-color: white;"> 1
</span><b style="background-color: white;">}</b><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">zfs_mount_handler ()</span><span style="background-color: white;"> </span><b style="background-color: white;">{</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">local</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">node=$1</span><span style="background-color: white;">
</span><b style="background-color: white;">if</b><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$ZFS_DATASET</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">=</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"bootfs"</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;"> ; </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><b style="background-color: white;">if</b><span style="background-color: white;"> ! </span><span style="background-color: white; color: #0095ff;">zfs_get_bootfs</span><span style="background-color: white;"> </span><b style="background-color: white;">;</b><span style="background-color: white;"> </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><span style="background-color: white; color: #898887;"># Lets import everything and try again</span><span style="background-color: white;">
</span><span style="background-color: white; color: #0095ff;">/usr/bin/zpool</span><span style="background-color: white;"> import </span><span style="background-color: white; color: #0057ae;">$ZPOOL_IMPORT_FLAGS</span><span style="background-color: white;"> -N -a </span><span style="background-color: white; color: #0057ae;">$ZPOOL_FORCE</span><span style="background-color: white;">
</span><b style="background-color: white;">if</b><span style="background-color: white;"> ! </span><span style="background-color: white; color: #0095ff;">zfs_get_bootfs</span><span style="background-color: white;"> </span><b style="background-color: white;">;</b><span style="background-color: white;"> </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">echo</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"ZFS: Cannot find bootfs."</span><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">return</span></b><span style="background-color: white;"> 1
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">local</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">pool=</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">${ZFS_DATASET%%</span><span style="background-color: white;">/*</span><span style="background-color: white; color: #0057ae;">}</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">local</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">rwopt_exp=${rwopt:-</span><span style="background-color: white;">ro</span><span style="background-color: white; color: #0057ae;">}</span><span style="background-color: white;">
</span><b style="background-color: white;">if</b><span style="background-color: white;"> ! </span><span style="background-color: white; color: #bf0303;">"/usr/bin/zpool"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #0095ff;">list</span><span style="background-color: white;"> -H </span><span style="background-color: white; color: #0057ae;">$pool</span><span style="background-color: white;"> 2>&1 > /dev/null </span><b style="background-color: white;">;</b><span style="background-color: white;"> </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><b style="background-color: white;">if</b><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$rwopt_exp</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">!=</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"rw"</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;">; </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0095ff;">msg</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"ZFS: Importing pool </span><span style="background-color: white; color: #0057ae;">$pool</span><span style="background-color: white; color: #bf0303;"> readonly."</span><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">ZPOOL_IMPORT_FLAGS=</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$ZPOOL_IMPORT_FLAGS</span><span style="background-color: white; color: #bf0303;"> -o readonly=on"</span><span style="background-color: white;">
</span><b style="background-color: white;">else</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0095ff;">msg</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"ZFS: Importing pool </span><span style="background-color: white; color: #0057ae;">$pool</span><span style="background-color: white; color: #bf0303;">."</span><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><i style="background-color: yellow;"><b>if</b> ! <span style="color: #bf0303;">"/usr/bin/zpool"</span> <span style="color: #0095ff;">import</span> <span style="color: #0057ae;">$ZPOOL_IMPORT_FLAGS</span> -N <span style="color: #0057ae;">$pool</span> <span style="color: #0057ae;">$ZPOOL_FORCE</span> <b>;</b> <b>then</b>
<b><span style="color: #644a9b;">echo</span></b> <span style="color: #bf0303;">"ZFS: Unable to import pool </span><span style="color: #0057ae;">$pool</span><span style="color: #bf0303;">. Sleeping for 10 seconds and then tying again."</span>
<span style="color: #644a9b;">sleep</span> 10
<b>if</b> ! <span style="color: #bf0303;">"/usr/bin/zpool"</span> <span style="color: #0095ff;">import</span> -d /dev -N <span style="color: #0057ae;">$pool</span> -f <b>;</b> <b>then</b>
<b><span style="color: #644a9b;">echo</span></b> <span style="color: #bf0303;">"ZFS: Unable to import pool </span><span style="color: #0057ae;">$pool</span><span style="color: #bf0303;">. Sleeping for 60 seconds and then trying yet again."</span>
<span style="color: #644a9b;">sleep</span> 60
<b>if</b> ! <span style="color: #bf0303;">"/usr/bin/zpool"</span> <span style="color: #0095ff;">import</span> -d /dev -N <span style="color: #0057ae;">$pool</span> -f <b>;</b> <b>then</b>
<b><span style="color: #644a9b;">echo</span></b> <span style="color: #bf0303;">"ZFS: Unable to import pool </span><span style="color: #0057ae;">$pool</span><span style="color: #bf0303;">, even after waiting a good long time for devices to show up."</span>
<b><span style="color: #644a9b;">return</span></b> 1
<b>fi</b>
<b>fi</b>
<b>fi</b></i><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">local</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">mountpoint=$(</span><span style="background-color: white; color: #bf0303;">"/usr/bin/zfs"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #0095ff;">get</span><span style="background-color: white;"> -H -o value mountpoint </span><span style="background-color: white; color: #0057ae;">$ZFS_DATASET)</span><span style="background-color: white;">
</span><b style="background-color: white;">if</b><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$mountpoint</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">=</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"legacy"</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;"> ; </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">mount</span><span style="background-color: white;"> -t zfs -o </span><span style="background-color: white; color: #0057ae;">${rwopt_exp}</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$ZFS_DATASET</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$node</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;">
</span><b style="background-color: white;">else</b><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">mount</span><span style="background-color: white;"> -o zfsutil,</span><span style="background-color: white; color: #0057ae;">${rwopt_exp}</span><span style="background-color: white;"> -t zfs </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$ZFS_DATASET</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$node</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;">}</b><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">run_hook()</span><span style="background-color: white;"> </span><b style="background-color: white;">{</b><span style="background-color: white;">
</span><span style="background-color: white; color: #898887;"># Force import the pools, useful if the pool has not properly been exported</span><span style="background-color: white;">
</span><span style="background-color: white; color: #898887;"># using 'zpool export <pool>'</pool></span><span style="background-color: white;">
</span><b style="background-color: white;"> [[</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">$zfs_force</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">==</span><span style="background-color: white;"> 1</span><b style="background-color: white;"> ]]</b><span style="background-color: white;"> </span><b style="background-color: white;">&&</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">ZPOOL_FORCE=</span><span style="background-color: white; color: #bf0303;">'-f'</span><span style="background-color: white;">
</span><b style="background-color: white;"> [[</b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$zfs_import_dir</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">!=</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">""</span><b style="background-color: white;"> ]]</b><span style="background-color: white;"> </span><b style="background-color: white;">&&</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">ZPOOL_IMPORT_FLAGS=</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$ZPOOL_IMPORT_FLAGS</span><span style="background-color: white; color: #bf0303;"> -d </span><span style="background-color: white; color: #0057ae;">$zfs_import_dir</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;">
</span><b style="background-color: white;">if</b><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white; color: #0057ae;">$root</span><span style="background-color: white; color: #bf0303;">"</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">=</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">'zfs'</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;">; </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">mount_handler=</span><span style="background-color: white; color: #bf0303;">'zfs_mount_handler'</span><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><b style="background-color: white;">case</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0057ae;">$zfs</span><b style="background-color: white;"> in</b><span style="background-color: white;">
auto</span><b style="background-color: white;">|</b><span style="background-color: white;">bootfs</span><b style="background-color: white;">)</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">ZFS_DATASET=</span><span style="background-color: white; color: #bf0303;">'bootfs'</span><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">mount_handler=</span><span style="background-color: white; color: #bf0303;">"zfs_mount_handler"</span><span style="background-color: white;">
</span><b style="background-color: white;">;;</b><span style="background-color: white;">
*</span><b style="background-color: white;">)</b><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">ZFS_DATASET=$zfs</span><span style="background-color: white;">
</span><span style="background-color: white; color: #0057ae;">mount_handler=</span><span style="background-color: white; color: #bf0303;">"zfs_mount_handler"</span><span style="background-color: white;">
</span><b style="background-color: white;">;;</b><span style="background-color: white;">
</span><b style="background-color: white;">esac</b><span style="background-color: white;">
</span><b style="background-color: white;">if</b><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">!</span><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">-f</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"/etc/hostid"</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;"> ; </span><b style="background-color: white;">then</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;">echo</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"ZFS: No hostid found on kernel command line or /etc/hostid. ZFS pools may not import correctly."</span><span style="background-color: white;">
</span><b style="background-color: white;">fi</b><span style="background-color: white;">
</span><span style="background-color: white; color: #898887;"># Allow up to 10 seconds for zfs device to show up</span><span style="background-color: white;">
</span><b style="background-color: white;">for</b><span style="background-color: white;"> </span><span style="background-color: white; color: #0095ff;">i</span><span style="background-color: white;"> in 1 2 3 4 5 6 7 8 9 10</span><b style="background-color: white;">;</b><span style="background-color: white;"> </span><b style="background-color: white;">do</b><span style="background-color: white;">
</span><b style="background-color: white;"><span style="color: #644a9b;"> [</span></b><span style="background-color: white;"> </span><span style="background-color: white; color: #006e28;">-c</span><span style="background-color: white;"> </span><span style="background-color: white; color: #bf0303;">"/dev/zfs"</span><b style="background-color: white;"><span style="color: #644a9b;"> ]</span></b><span style="background-color: white;"> </span><b style="background-color: white;">&&</b><span style="background-color: white;"> </span><b style="background-color: white;"><span style="color: #644a9b;">break</span></b><span style="background-color: white;">
</span><span style="background-color: white; color: #644a9b;">sleep</span><span style="background-color: white;"> 1
</span><b style="background-color: white;">done</b><span style="background-color: white;">
</span><b style="background-color: white;">}</b></span></pre>
<pre style="color: #1f1c1b;"><span style="font-family: Courier New, Courier, monospace;"><b style="background-color: white;"> </b></span></pre>
<pre style="color: #1f1c1b;"></pre>
Next, we run "mkinitcpio -p linux-lts", exit the chroot, "zpool export root_pool", reboot, and we see that the first zpool import attempt still fails. However, we are then into the code we added, which waits ten seconds and tries zpool importing again. This second attempt succeeds.<br />
<br />In summary: most likely, the "waiting for uevents" step that precedes the first import attempt does not do quite enough waiting. Waiting more and retrying works. There is some possibility that the import just fails the first time and works the second, but the point remains that waiting more and retrying works, and that's what we do.</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-38353438080573657842015-12-31T01:18:00.002+01:002015-12-31T01:22:18.393+01:00Doing anything significant whatsoever with QML: index<div>
<a href="http://esoerik.blogspot.com/2015/12/doing-anything-significant-whatsoever_30.html">Doing anything significant whatsoever with QML, part 5</a></div>
<a href="http://esoerik.blogspot.com/2015/12/doing-anything-significant-whatsoever_23.html">Doing anything significant whatsoever with QML, part 4</a><br />
<div>
<a href="http://esoerik.blogspot.com/2015/12/doing-anything-significant-whatsoever_20.html">Doing anything significant whatsoever with QML, part 3</a></div>
<div>
<a href="http://esoerik.blogspot.com/2015/12/doing-anything-significant-whatsoever.html">Doing anything significant whatsoever with QML, part 2</a></div>
<div>
<a href="http://esoerik.blogspot.com/2015/11/doing-anything-significant-whatsoever.html">Doing anything significant whatsoever with QML, part 1</a><br />
<br />
<a href="https://github.com/erikhvatum/StackStream/tree/3a35f1aff43c8a73da233f418729a6c07c6568fb">Complete source as it stood at the end of part 5</a>.</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-20478284870251926912015-12-30T05:42:00.001+01:002015-12-31T01:12:12.351+01:00Doing anything significant whatsoever with QML, part 5: ThirtyBitSGContext plugin and ThirtyBitSGLayer<div style="font-style: normal; font-variant: normal; letter-spacing: normal;">
<span style="color: black;"><span style="font-family: Georgia, serif;">As things stand at
the end of part 4, uncommenting the layer.enabled: true line in the
following QML results in resampling to 24-bit color, while leaving it
commented preserves 30-bit color:</span></span></div>
<div style="font-style: normal; font-variant: normal; letter-spacing: normal;">
<br />
</div>
<pre class="western"><u>ThirtyBitImageItem</u><span style="color: silver;"> </span>{
<span style="color: silver;"> </span>id:<span style="color: silver;"> </span>thirtyBitImageItem
<span style="color: silver;"> </span>objectName:<span style="color: silver;"> </span><span style="color: green;">"thirtyBitImageItem"</span>
<span style="color: silver;"> </span>anchors.horizontalCenter:<span style="color: silver;"> </span>parent.horizontalCenter
<span style="color: silver;"> </span>anchors.top:<span style="color: silver;"> </span>parent.top
<span style="color: silver;"> </span>anchors.bottom:<span style="color: silver;"> </span>parent.bottom
<span style="color: silver;"> </span>width:<span style="color: silver;"> </span>(implicitWidth<span style="color: silver;"> </span>/<span style="color: silver;"> </span>implicitHeight)<span style="color: silver;"> </span>*<span style="color: silver;"> </span>height
<span style="color: silver;"> </span>anchors.margins:<span style="color: silver;"> </span>10
<span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;"><b>layer.enabled:</b></span><span style="color: silver;"><b> </b></span><span style="color: green;"><b>true</b></span>
}</pre>
<br />
<br />
Fixing this requires understanding the effect of that
<span style="font-family: Liberation Mono, monospace;">layer.enabled: true</span>
QML statement. Let's see what the Qt documentation has to say:<br />
<span style="font-family: Liberation Serif, serif;"><i><b>layer.enabled</b> :
bool</i></span><br />
<div style="margin-bottom: 0in; margin-left: 0.49in;">
<span style="font-family: Liberation Serif, serif;"><i>Holds
whether the item is layered or not. Layering is disabled by default.</i></span></div>
<div style="margin-bottom: 0in; margin-left: 0.49in;">
<span style="font-family: Liberation Serif, serif;"><i>A
layered item is rendered into an offscreen surface and cached until
it is changed. Enabling layering for complex QML item hierarchies can
sometimes be an optimization.</i></span></div>
<div style="margin-bottom: 0in; margin-left: 0.49in;">
<span style="font-family: Liberation Serif, serif;"><i>None
of the other layer properties have any effect when the layer is
disabled.</i></span></div>
<div style="margin-bottom: 0in; margin-left: 0.49in;">
<br />
</div>
Good documentation; a normal person could read that and understand
it. In other words, the documentation is irrelevant to our
situation. We must turn to the Qt source code itself, but where do
we look? It's easy to spot the <span style="font-family: Liberation Mono, monospace;">QObject</span>
half of a layer (<span style="font-family: Liberation Mono, monospace;"><span style="font-style: normal;"><span style="font-weight: normal;">QQuickItemLayer</span></span></span><span style="font-style: normal;">
in </span><i>qtdeclarative/src/quick/items/qquickitem_p.h</i>).
However, locating the scene graph half requires detective work. If
the layer scene-graph-node-class's name follows convention, it will
be <span style="font-family: Liberation Mono, monospace;">QSGLayer</span>. However,
there is no file named <i>qsglayer.cpp</i> in the Qt5 source tree.
Perhaps, wherever <span style="font-family: Liberation Mono, monospace;">QSGLayer</span>
is defined, it's a pure virtual interface class? In that case,
finding it wouldn't help, and the Qt5 source tree is rather large, so
I don't feel like grepping through it anyway. Munging around with a
C++ debugger attached to a minimal QML application with a single item
having <span style="font-family: Liberation Mono, monospace;">layer.enabled: true</span>
reveals that the <span style="font-family: Liberation Mono, monospace;">layer.enabled</span>:
true statement ultimately causes invocation of <span style="font-family: Liberation Mono, monospace;">QSGLayer
*QSGContext::createLayer(QSGRenderContext *renderContext)</span>,
defined in <i>qtdeclarative/src/quick/scenegraph/qsgcontext.cpp</i><span style="font-style: normal;">:</span><br />
<div style="font-style: normal;">
<br />
</div>
<pre class="western"><span style="color: purple;"><span style="font-style: normal;">QSGLayer</span></span><span style="color: silver;"><span style="font-style: normal;"> </span></span><span style="color: black;"><span style="font-style: normal;">*</span></span><span style="color: purple;"><span style="font-style: normal;">QSGContext</span></span><span style="color: black;"><span style="font-style: normal;">::</span></span><span style="color: black;"><i>createLayer</i></span><span style="color: black;"><span style="font-style: normal;">(</span></span><span style="color: purple;"><span style="font-style: normal;">QSGRenderContext</span></span><span style="color: silver;"><span style="font-style: normal;"> </span></span><span style="color: black;"><span style="font-style: normal;">*renderContext)</span></span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QSGDefaultLayer</span><span style="color: black;">(renderContext);</span>
<span style="color: black;">}</span></pre>
<div style="font-style: normal;">
<br />
</div>
Ah ha! <span style="font-family: Liberation Mono, monospace;"><span style="font-weight: normal;">QSGDefaultLayer</span></span><span style="font-weight: normal;">
is the actual </span><span style="font-family: Liberation Mono, monospace;"><span style="font-weight: normal;">QSGLayer</span></span><span style="font-weight: normal;">
derivative that is instantiated. And, there is a </span><i><span style="font-weight: normal;">qsgdefaultlayer.cpp</span></i><span style="font-weight: normal;">
(</span><i><span style="font-weight: normal;">qtdeclarative/src/quick/scenegraph/qsgdefaultlayer.cpp</span></i><span style="font-style: normal;"><span style="font-weight: normal;">).
</span></span><span style="font-style: normal;"><span style="font-weight: normal;">Relevant</span></span><span style="font-style: normal;"><span style="font-weight: normal;">
excerpts </span></span><span style="font-style: normal;"><span style="font-weight: normal;">from
that file</span></span><span style="font-style: normal;"><span style="font-weight: normal;">:</span></span><br />
<div style="font-style: normal; font-weight: normal;">
<br />
<br />
</div>
<pre class="western"><span style="color: purple;">QSGDefaultLayer</span><span style="color: black;">::QSGDefaultLayer(</span><span style="color: purple;">QSGRenderContext</span><span style="color: silver;"> </span><span style="color: black;">*context)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: purple;">QSGLayer</span><span style="color: black;">()</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_device_pixel_ratio</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: black;">(</span><span style="color: navy;"><b>GL_RGBA</b></span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">(context)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_live</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_recursive</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisamplingChecked</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisampling</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: black;">{</span>
<span style="color: black;">}</span></pre>
<br />
<br />
<br />
<pre class="western"><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QSGDefaultLayer</span><span style="color: black;">::</span><span style="color: black;"><i>bind</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_DEBUG</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_recursive</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">((</span><span style="color: maroon;">m_multisampling</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">->isBound())</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->isBound()))</span>
<span style="color: silver;"> </span><span style="color: navy;">qWarning</span><span style="color: black;">(</span><span style="color: green;">"ShaderEffectSource:</span><span style="color: silver;"> </span><span style="color: green;">\'recursive\'</span><span style="color: silver;"> </span><span style="color: green;">must</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">set</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">true</span><span style="color: silver;"> </span><span style="color: green;">when</span><span style="color: silver;"> </span><span style="color: green;">rendering</span><span style="color: silver;"> </span><span style="color: green;">recursively."</span><span style="color: black;">);</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::currentContext()->functions();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;"><b>GL_RGBA</b></span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_transparentTexture</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glGenTextures(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: black;">zero</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glTexImage2D(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;"><b>GL_RGBA</b></span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;"><b>GL_RGBA</b></span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_BYTE</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&zero);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;"><b>m_fbo</b></span><span style="color: silver;"><b> </b></span><span style="color: black;"><b>?</b></span><span style="color: silver;"><b> </b></span><span style="color: maroon;"><b>m_fbo</b></span><span style="color: black;"><b>->texture()</b></span><span style="color: silver;"><b> </b></span><span style="color: black;"><b>:</b></span><span style="color: silver;"><b> </b></span><span style="color: navy;"><b>0</b></span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span></pre>
<br />
<br />
<br />
Interestingly, even though it didn't work for us, there is
apparently a codepath for wacko framebuffer formats that avoids
resampling. I may eventually revisit this.<br />
<br />
As with ThirtyBitSGTexture vs QSGTexture, the changes required to
implement ThirtyBitLayer from QSGDefaultLayer's code are minimal.
However, in order to make setting layer.enabled: true cause
instantiation of ThirtyBitLayer, we must override
QSGContext::createLayer(..), which requires us to derive our own
QSGContext, ThirtyBitSGContext. In turn, making Qt use our
ThirtyBitSGContext requires overriding
QSGContext::createDefaultContext(), declared in
<i>qtdeclarative/src/quick/scenegraph/qsgcontextplugin.cpp</i>. So,
we need to make a plugin, and then somehow tell Qt about it, and then
somehow get Qt to use it.<br />
<br />
The Qt documentation touches on this only briefly:<br />
<br />
<div style="margin-left: 0.49in;">
<i><b>Scene Graph Backend</b></i></div>
<div style="margin-left: 0.49in;">
<i><b><br /></b></i></div>
<div style="margin-bottom: 0.06in; margin-left: 0.49in;">
<i>In addition
to the public API, the scene graph has an adaptation layer which
opens up the implementation to do hardware specific adaptations. This
is an undocumented, internal and private plugin API, which lets
hardware adaptation teams make the most of their hardware. It
includes:</i></div>
<ul>
<li>
<div style="margin-bottom: 0.06in; margin-top: 0.04in;">
<i>Custom
textures; specifically the implementation of
QQuickWindow::createTextureFromImage and the internal representation
of the texture used by Image and BorderImage types.</i></div>
</li>
<li>
<div style="margin-bottom: 0.06in; margin-top: 0.04in;">
<i>Custom
renderer; the adaptation layer lets the plugin decide how the scene
graph is traversed and rendered, making it possible to optimize the
rendering algorithm for a specific hardware or to make use of
extensions which improve performance.</i></div>
</li>
<li>
<div style="margin-bottom: 0.06in; margin-top: 0.04in;">
<i>Custom
scene graph implementation of many of the default QML types,
including its text and font rendering.</i></div>
</li>
<li>
<div style="margin-bottom: 0.06in; margin-top: 0.04in;">
<i>Custom
animation driver; allows the animation system to hook into the
low-level display vertical refresh to get smooth rendering.</i></div>
</li>
<li>
<div style="margin-bottom: 0.06in; margin-top: 0.04in;">
<i>Custom
render loop; allows better control over how QML deals with multiple
windows. </i>
</div>
</li>
</ul>
Again, the docs tell us what we've already deduced, and we turn to
the source (<i>qtdeclarative/src/quick/scenegraph/qsgcontextplugin.cpp</i>):<br />
<br />
<pre class="western"><span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_LIBRARY</span>
<span style="color: navy;">Q_GLOBAL_STATIC_WITH_ARGS</span><span style="color: black;">(</span>QFactoryLoader<span style="color: black;">,</span><span style="color: silver;"> </span>loader<span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: navy;">QSGContextFactoryInterface_iid</span><span style="color: black;">,</span><span style="color: silver;"> </span>QLatin1String<span style="color: black;">(</span><span style="color: green;">"/scenegraph"</span><span style="color: black;">)))</span>
<span style="color: navy;">#endif</span>
<span style="color: olive;">struct</span><span style="color: silver;"> </span><span style="color: purple;">QSGAdaptionPluginData</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGAdaptionPluginData</span><span style="color: black;">()</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">tried</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">factory</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">~</span><span style="color: purple;">QSGAdaptionPluginData</span><span style="color: black;">()</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">tried</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGContextFactoryInterface</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">factory</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QString</span><span style="color: silver;"> </span><span style="color: maroon;">deviceName</span><span style="color: black;">;</span>
<span style="color: black;">};</span>
<span style="color: navy;">Q_GLOBAL_STATIC</span><span style="color: black;">(</span>QSGAdaptionPluginData<span style="color: black;">,</span><span style="color: silver;"> </span>qsg_adaptation_data<span style="color: black;">)</span>
<span style="color: navy;">/*!</span>
<span style="color: silver;"> </span><span style="color: blue;">\fn</span><span style="color: silver;"> </span><span style="color: navy;">QSGContext</span><span style="color: silver;"> </span><span style="color: navy;">*QSGContext::createDefaultContext()</span>
<span style="color: silver;"> </span><span style="color: navy;">Creates</span><span style="color: silver;"> </span><span style="color: navy;">a</span><span style="color: silver;"> </span><span style="color: navy;">default</span><span style="color: silver;"> </span><span style="color: navy;">scene</span><span style="color: silver;"> </span><span style="color: navy;">graph</span><span style="color: silver;"> </span><span style="color: navy;">context</span><span style="color: silver;"> </span><span style="color: navy;">for</span><span style="color: silver;"> </span><span style="color: navy;">the</span><span style="color: silver;"> </span><span style="color: navy;">current</span><span style="color: silver;"> </span><span style="color: navy;">hardware.</span>
<span style="color: silver;"> </span><span style="color: navy;">This</span><span style="color: silver;"> </span><span style="color: navy;">may</span><span style="color: silver;"> </span><span style="color: navy;">load</span><span style="color: silver;"> </span><span style="color: navy;">a</span><span style="color: silver;"> </span><span style="color: navy;">device-specific</span><span style="color: silver;"> </span><span style="color: navy;">plugin.</span>
<span style="color: navy;">*/</span>
<span style="color: purple;">QSGContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: purple;">QSGContext</span><span style="color: black;">::createDefaultContext()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGAdaptionPluginData</span><span style="color: silver;"> </span><span style="color: black;">*plugin</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">contextFactory();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(plugin-></span><span style="color: maroon;">factory</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;"><b>return</b></span><span style="color: silver;"><b> </b></span><span style="color: black;"><b>plugin-></b></span><span style="color: maroon;"><b>factory</b></span><span style="color: black;"><b>-></b></span><span style="color: black;"><i><b>create</b></i></span><span style="color: black;"><b>(plugin-></b></span><span style="color: maroon;"><b>deviceName</b></span><span style="color: black;"><b>);</b></span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QSGContext</span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGAdaptionPluginData</span><span style="color: silver;"> </span><span style="color: black;">*contextFactory()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGAdaptionPluginData</span><span style="color: silver;"> </span><span style="color: black;">*plugin</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>qsg_adaptation_data<span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!plugin-></span><span style="color: maroon;">tried</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">plugin-></span><span style="color: maroon;">tried</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QStringList</span><span style="color: silver;"> </span><span style="color: black;">args</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QGuiApplication</span><span style="color: black;">::arguments();</span>
<span style="color: silver;"> </span><span style="color: purple;">QString</span><span style="color: silver;"> </span><span style="color: black;">device;</span>
<span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;">index</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">index</span><span style="color: silver;"> </span><span style="color: black;"><</span><span style="color: silver;"> </span><span style="color: black;">args.count();</span><span style="color: silver;"> </span><span style="color: black;">++index)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(args.at(index).</span>startsWith<span style="color: black;">(</span><span style="color: purple;">QLatin1String</span><span style="color: black;">(</span><span style="color: green;">"--device="</span><span style="color: black;">)))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">device</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">args.at(index).</span>mid<span style="color: black;">(</span><span style="color: navy;">9</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(device.isEmpty())</span>
<span style="color: silver;"> </span><span style="color: black;">device</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QString</span><span style="color: black;">::fromLocal8Bit(qgetenv(</span><span style="color: green;">"QMLSCENE_DEVICE"</span><span style="color: black;">));</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_LIBRARY</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!device.isEmpty())</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;"><b>const</b></span><span style="color: silver;"><b> </b></span><span style="color: olive;"><b>int</b></span><span style="color: silver;"><b> </b></span><span style="color: black;"><b>index</b></span><span style="color: silver;"><b> </b></span><span style="color: black;"><b>=</b></span><span style="color: silver;"><b> </b></span><b>loader</b><span style="color: black;"><b>()-></b></span><b>indexOf</b><span style="color: black;"><b>(device);</b></span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(index</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: navy;">1</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">plugin-></span><span style="color: maroon;">factory</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">qobject_cast<</span><span style="color: purple;">QSGContextFactoryInterface</span><span style="color: black;">*>(</span>loader<span style="color: black;">()-></span>instance<span style="color: black;">(index));</span>
<span style="color: silver;"> </span><span style="color: black;">plugin-></span><span style="color: maroon;">deviceName</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">device;</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_DEBUG</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!plugin-></span><span style="color: maroon;">factory</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: navy;">qWarning</span><span style="color: black;">(</span><span style="color: green;">"Could</span><span style="color: silver;"> </span><span style="color: green;">not</span><span style="color: silver;"> </span><span style="color: green;">create</span><span style="color: silver;"> </span><span style="color: green;">scene</span><span style="color: silver;"> </span><span style="color: green;">graph</span><span style="color: silver;"> </span><span style="color: green;">context</span><span style="color: silver;"> </span><span style="color: green;">for</span><span style="color: silver;"> </span><span style="color: green;">device</span><span style="color: silver;"> </span><span style="color: green;">'%s'"</span>
<span style="color: silver;"> </span><span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">-</span><span style="color: silver;"> </span><span style="color: green;">check</span><span style="color: silver;"> </span><span style="color: green;">that</span><span style="color: silver;"> </span><span style="color: green;">plugins</span><span style="color: silver;"> </span><span style="color: green;">are</span><span style="color: silver;"> </span><span style="color: green;">installed</span><span style="color: silver;"> </span><span style="color: green;">correctly</span><span style="color: silver;"> </span><span style="color: green;">in</span><span style="color: silver;"> </span><span style="color: green;">%s"</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">qPrintable</span><span style="color: black;">(device),</span>
<span style="color: silver;"> </span><span style="color: navy;">qPrintable</span><span style="color: black;">(</span><span style="color: purple;">QLibraryInfo</span><span style="color: black;">::location(</span><span style="color: purple;">QLibraryInfo</span><span style="color: black;">::</span><span style="color: purple;">PluginsPath</span><span style="color: black;">)));</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: navy;">#endif</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">QT_NO_LIBRARY</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">plugin;</span>
<span style="color: black;">}</span></pre>
<pre class="western"><span style="color: black;">
</span></pre>
The key lines of code are bolded. We want <span style="font-family: Liberation Mono, monospace;">createDefaultContext()</span>
to return an instance of <span style="font-family: Liberation Mono, monospace;">ThirtyBitSGContext</span>.
In order for that to happen, <span style="font-family: Liberation Mono, monospace;">contextFactory()</span>
has to discover our plugin. With the <span style="font-family: Liberation Mono, monospace;">QMLSCENE_DEVICE</span>
environment variable set to <span style="font-family: Liberation Mono, monospace;">ThirtyBitSGContextPlugin</span>,
the following is sufficient for plugin discovery:<br />
<br />
<i>ThirtyBitSGContextPlugin.h</i>:<br />
<br />
<pre class="western"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtCore/qplugin.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgcontext_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgcontextplugin_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QObject></span>
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">QSGContextFactoryInterface</span><span style="color: black;">;</span>
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContextPlugin</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QObject</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QSGContextFactoryInterface</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_OBJECT</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_PLUGIN_METADATA</span><span style="color: black;">(</span>IID<span style="color: silver;"> </span><span style="color: green;">"org.qt-project.Qt.QSGContextFactoryInterface"</span><span style="color: silver;"> </span>FILE<span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContextPlugin.json"</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: purple;">Q_INTERFACES</span><span style="color: black;">(</span><span style="color: purple;">QSGContextFactoryInterface</span><span style="color: black;">:</span><span style="color: purple;">QFactoryInterface</span><span style="color: black;">)</span>
<span style="color: olive;">public</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContextPlugin</span><span style="color: black;">(</span><span style="color: purple;">QObject</span><span style="color: silver;"> </span><span style="color: black;">*</span>parent<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGContext</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;"><i>create</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QString</span><span style="color: black;">&</span><span style="color: silver;"> </span>key<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QStringList</span><span style="color: silver;"> </span><span style="color: black;"><i>keys</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">virtual</span><span style="color: silver;"> </span><span style="color: purple;">QQuickTextureFactory</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;"><i>createTextureFactoryFromImage</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">&)</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">virtual</span><span style="color: silver;"> </span><span style="color: purple;">QSGRenderLoop</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;"><i>createWindowManager</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">};</span></pre>
<br />
<br />
<br />
<i>ThirtyBitSGContextPlugin.cpp</i>:<br />
<pre class="western"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContextPlugin.h"</span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContext.h"</span>
<span style="color: black;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContextPlugin.h"</span></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContext.h"</span>
<span style="color: purple;">ThirtyBitSGContextPlugin</span><span style="color: black;">::ThirtyBitSGContextPlugin(</span><span style="color: purple;">QObject</span><span style="color: silver;"> </span><span style="color: black;">*parent)</span><span style="color: silver;"> </span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: purple;">QObject</span><span style="color: black;">(parent)</span>
<span style="color: black;">{</span>
<span style="color: black;">}</span>
<span style="color: purple;">QStringList</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContextPlugin</span><span style="color: black;">::</span><span style="color: black;"><i>keys</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">This</span><span style="color: silver;"> </span><span style="color: green;">never</span><span style="color: silver;"> </span><span style="color: green;">seems</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">invoked.</span><span style="color: silver;"> </span><span style="color: green;">Perhaps</span><span style="color: silver;"> </span><span style="color: green;">it</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">vestigial?</span><span style="color: silver;"> </span><span style="color: green;">It</span><span style="color: silver;"> </span><span style="color: green;">does</span><span style="color: silver;"> </span><span style="color: green;">appear</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">be</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">redundant,</span><span style="color: silver;"> </span><span style="color: green;">given</span><span style="color: silver;"> </span><span style="color: green;">that</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">json</span><span style="color: silver;"> </span><span style="color: green;">metadata</span><span style="color: silver;"> </span><span style="color: green;">file</span><span style="color: silver;"> </span><span style="color: green;">contains</span><span style="color: silver;"> </span><span style="color: green;">a</span><span style="color: silver;"> </span><span style="color: green;">"Keys"</span><span style="color: silver;"> </span><span style="color: green;">entry.</span>
<span style="color: silver;"> </span><span style="color: purple;">QStringList</span><span style="color: silver;"> </span><span style="color: black;">ret;</span>
<span style="color: silver;"> </span><span style="color: black;">ret</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContextPlugin"</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">ret;</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGContext</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContextPlugin</span><span style="color: black;">::</span><span style="color: black;"><i>create</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QString</span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: black;">key)</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContext</span><span style="color: black;">();</span>
<span style="color: black;">}</span>
</pre>
<i>ThirtyBitSGContextPlugin.json</i>:<br />
<pre class="western">{
<span style="color: silver;"> </span><span style="color: green;">"Keys"</span><span style="color: silver;"> </span>:<span style="color: silver;"> </span>[<span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContextPlugin"</span><span style="color: silver;"> </span>]
}</pre>
<br />
<br />
<br />
As for ThirtyBitSGContext, there's not much to it:<br />
<br />
<i>ThirtyBitSGContext.h</i>:<br />
<br />
<pre class="western"><span style="color: navy;">#pragma</span><span style="color: silver;"> </span>once
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">QSGContext</span><span style="color: black;">;</span>
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">QSGLayer</span><span style="color: black;">;</span>
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContext</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QSGContext</span>
<span style="color: black;">{</span>
<span style="color: olive;">public</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: olive;">explicit</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContext</span><span style="color: black;">(</span>QObject<span style="color: black;">*</span><span style="color: silver;"> </span>parent<span style="color: black;">=</span><span style="color: olive;">nullptr</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGLayer</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">createLayer(</span>QSGRenderContext<span style="color: black;">*</span><span style="color: silver;"> </span>renderContext<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: black;">;</span>
<span style="color: black;">};</span></pre>
<br />
<br />
<br />
<i>ThirtyBitSGContext.cpp</i>:<br />
<pre class="western"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgcontext_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgdefaultlayer_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGContext.h"</span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGLayer.h"</span>
<span style="color: purple;">ThirtyBitSGContext</span><span style="color: black;">::ThirtyBitSGContext(</span><span style="color: purple;">QObject</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">parent)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: purple;">QSGContext</span><span style="color: black;">(parent)</span>
<span style="color: black;">{</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGLayer</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGContext</span><span style="color: black;">::</span><span style="color: black;"><i>createLayer</i></span><span style="color: black;">(</span><span style="color: purple;">QSGRenderContext</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">renderContext)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: navy;">qDebug</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: green;">"QSGLayer*</span><span style="color: silver;"> </span><span style="color: green;">createLayer(QSGRenderContext*</span><span style="color: silver;"> </span><span style="color: green;">renderContext)"</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">(renderContext);</span>
<span style="color: black;">}</span></pre>
<br />
<br />
<span style="font-family: Liberation Mono, monospace;">ThirtyBitSGLayer</span> is
necessarily more complex as we can not inherit from <span style="font-family: Liberation Mono, monospace;">QSGDefaultLayer</span>,
owing to the fact that we would need to access private members. I
consider this to be obnoxious and unnecessary: <span style="font-family: Liberation Mono, monospace;">QSGDefaultLayer</span>
is already part of the Qt “private” API; throwing up additional
roadblocks helps nobody. So, fuck its privacy. <span style="font-style: normal;"><span style="font-weight: normal;">We</span></span><span style="font-style: normal;"><span style="font-weight: normal;">'ll</span></span><span style="font-style: normal;"><span style="font-weight: normal;">
just go right ahead</span></span><span style="font-weight: normal;">
</span><span style="font-weight: normal;">and </span><span style="font-weight: normal;">copy/paste
the entire </span><span style="font-weight: normal;">thing, </span><span style="font-weight: normal;">and
then</span><span style="font-weight: normal;"> </span><span style="font-weight: normal;">we</span><span style="font-weight: normal;">'ll</span><span style="font-weight: normal;">
</span><span style="font-weight: normal;">make whatever changes </span><span style="font-weight: normal;">we
want</span><span style="font-weight: normal;"> </span><span style="font-style: normal;"><span style="font-weight: normal;">(</span></span><span style="font-style: normal;"><span style="font-weight: normal;">important
</span></span><span style="font-style: normal;"><span style="font-weight: normal;">changes
</span></span><span style="font-style: normal;"><span style="font-weight: normal;">in
</span></span><span style="font-style: normal;"><span style="font-weight: normal;">bold).</span></span><br />
<span style="font-style: normal;"><span style="font-weight: normal;"><br /></span></span>
<i>ThirtyBitSGLayer.h</i><span style="font-style: normal;">:</span><br />
<span style="font-style: normal;"><br /></span>
<pre class="western"><span style="color: navy;"><span style="font-style: normal;">#pragma</span></span><span style="color: silver;"><span style="font-style: normal;"> </span></span><span style="color: green;"><span style="font-style: normal;">once</span></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgadaptationlayer_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgcontext_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< qsgsimplerectnode.h></span>
<span style="color: navy;">#define</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QSGLayer</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_OBJECT</span>
<span style="color: olive;">public</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">(</span><span style="color: purple;">QSGRenderContext</span><span style="color: silver;"> </span><span style="color: black;">*</span>context<span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">~</span><span style="color: black;"><i>ThirtyBitSGLayer</i></span><span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;"><i>updateTexture</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">The</span><span style="color: silver;"> </span><span style="color: green;">item's</span><span style="color: silver;"> </span><span style="color: green;">"paint</span><span style="color: silver;"> </span><span style="color: green;">node",</span><span style="color: silver;"> </span><span style="color: green;">not</span><span style="color: silver;"> </span><span style="color: green;">effect</span><span style="color: silver;"> </span><span style="color: green;">node.</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*item()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setItem</i></span><span style="color: black;">(</span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*</span>item<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: black;">rect()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setRect</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: black;">&</span>rect<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;">size()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setSize</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;">&</span>size<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setHasMipmaps</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span>mipmap<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>bind</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;"><i>hasAlphaChannel</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;"><i>hasMipmaps</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;"><i>textureId</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;"><i>textureSize</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span><span style="color: black;">format()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setFormat</i></span><span style="color: black;">(</span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span>format<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">live()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setLive</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span>live<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">recursive()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: black;">(</span><span style="color: maroon;">m_recursive</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setRecursive</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span>recursive<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setDevicePixelRatio</i></span><span style="color: black;">(</span><span style="color: purple;">qreal</span><span style="color: silver;"> </span><span style="color: black;">ratio)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: maroon;">m_device_pixel_ratio</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">ratio;</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">mirrorHorizontal()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: black;">(</span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setMirrorHorizontal</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span>mirror<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">mirrorVertical()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: black;">(</span><span style="color: maroon;">m_mirrorVertical</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>setMirrorVertical</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span>mirror<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>scheduleUpdate</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;"><i>toImage</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: black;"><i>normalizedTextureSubRect</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">Q_SLOTS</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>invalidated</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: olive;"><b>protected</b></span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">grab();</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_item</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">qreal</span><span style="color: silver;"> </span><span style="color: maroon;">m_device_pixel_ratio</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGRenderer</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_renderer</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSharedPointer</span><span style="color: black;"><</span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">></span><span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">GLuint</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">;</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGSimpleRectNode</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">;</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGRenderContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_context</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_recursive</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisamplingChecked</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisampling</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span>
<span style="color: black;">};</span></pre>
<pre class="western"><span style="color: black;">
</span></pre>
<i>ThirtyBitSGLayer.cpp</i>:<br />
<br />
<pre class="western"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgdefaultlayer_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QOpenGLFramebufferObject></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGLayer.h"</span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQml/private/qqmlglobal_p.h></span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgrenderer_p.h></span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: navy;">DEFINE_BOOL_CONFIG_OPTION</span><span style="color: black;">(</span>qmlFboOverlay<span style="color: black;">,</span><span style="color: silver;"> </span>QML_FBO_OVERLAY<span style="color: black;">)</span>
<span style="color: navy;">#endif</span>
<span style="color: navy;">DEFINE_BOOL_CONFIG_OPTION</span><span style="color: black;">(</span>qmlFboFlushBeforeDetach<span style="color: black;">,</span><span style="color: silver;"> </span>QML_FBO_FLUSH_BEFORE_DETACH<span style="color: black;">)</span>
<span style="color: olive;">namespace</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">BindableFbo</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QSGBindable</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: purple;">BindableFbo</span><span style="color: black;">(</span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: silver;"> </span><span style="color: black;">*</span>fbo<span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">*</span>depthStencil<span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">virtual</span><span style="color: silver;"> </span><span style="color: black;">~</span><span style="color: black;"><i>BindableFbo</i></span><span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;"><i>bind</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: navy;">Q_DECL_OVERRIDE</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">private</span><span style="color: black;">:</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">};</span>
<span style="color: silver;"> </span><span style="color: purple;">BindableFbo</span><span style="color: black;">::BindableFbo(</span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: silver;"> </span><span style="color: black;">*fbo,</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">*depthStencil)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">(fbo)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">(depthStencil)</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: purple;">BindableFbo</span><span style="color: black;">::~</span><span style="color: black;"><i>BindableFbo</i></span><span style="color: black;">()</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span>qmlFboFlushBeforeDetach<span style="color: black;">())</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::currentContext()->functions()->glFlush();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">->detach();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">BindableFbo</span><span style="color: black;">::</span><span style="color: black;"><i>bind</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->bind();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencil</span><span style="color: black;">->attach();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span>
<span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::ThirtyBitSGLayer(</span><span style="color: purple;">QSGRenderContext</span><span style="color: silver;"> </span><span style="color: black;">*context)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: purple;">QSGLayer</span><span style="color: black;">()</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_device_pixel_ratio</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: black;">(</span><span style="color: navy;"><b>GL_RGB10_A2</b></span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">(context)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_live</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_recursive</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisamplingChecked</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_multisampling</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span>
<span style="color: black;">{</span>
<span style="color: black;">}</span>
<span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::~</span><span style="color: black;"><i>ThirtyBitSGLayer</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;"><i>invalidated</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>invalidated</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::currentContext()->functions()->glDeleteTextures(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span>
<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>textureId</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->texture()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: black;">}</span>
<span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>hasAlphaChannel</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;"><b>switch</b></span><span style="color: black;"><b>(</b></span><span style="color: maroon;"><b>m_format</b></span><span style="color: black;"><b>)</b></span>
<span style="color: silver;"> </span><b><span style="color: black;">{</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB10</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB12</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB16</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB16F</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB32F</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">GL_R11F_G11F_B10F</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">default</span><span style="color: black;">:</span></b>
<span style="color: silver;"> </span><b><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></b>
<span style="color: silver;"> </span><b><span style="color: black;">}</span></b>
<span style="color: black;">}</span>
<span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>hasMipmaps</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: black;">;</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>bind</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span><span style="color: purple;">QT_NO_DEBUG</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_recursive</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">((</span><span style="color: maroon;">m_multisampling</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">->isBound())</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->isBound()))</span>
<span style="color: silver;"> </span><span style="color: navy;">qWarning</span><span style="color: black;">(</span><span style="color: green;">"ShaderEffectSource:</span><span style="color: silver;"> </span><span style="color: green;">\'recursive\'</span><span style="color: silver;"> </span><span style="color: green;">must</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">set</span><span style="color: silver;"> </span><span style="color: green;">to</span><span style="color: silver;"> </span><span style="color: green;">true</span><span style="color: silver;"> </span><span style="color: green;">when</span><span style="color: silver;"> </span><span style="color: green;">rendering</span><span style="color: silver;"> </span><span style="color: green;">recursively."</span><span style="color: black;">);</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::currentContext()->functions();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB10_A2</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_transparentTexture</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glGenTextures(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: black;">zero</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glTexImage2D(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;"><b>GL_RGB10_A2</b></span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGBA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_BYTE</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&zero);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_transparentTexture</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->texture()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span>
<span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>updateTexture</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">doGrab</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(doGrab)</span>
<span style="color: silver;"> </span><span style="color: black;">grab();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_grab</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">emit</span><span style="color: silver;"> </span><span style="color: black;">scheduledUpdateCompleted();</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">doGrab;</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setHasMipmaps</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">mipmap)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(mipmap</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">mipmap;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_mipmap</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">!</span><span style="color: maroon;">m_fbo</span><span style="color: black;">->format().mipmap())</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setItem</i></span><span style="color: black;">(</span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*item)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(item</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">item;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">!</span><span style="color: maroon;">m_item</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.clear();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setRect</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: black;">&rect)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(rect</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">rect;</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setSize</i></span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;">&size)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(size</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">size;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">.isNull())</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.clear();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setFormat</i></span><span style="color: black;">(</span><span style="color: purple;">GLenum</span><span style="color: black;">)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><b><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">NOPE!</span><span style="color: silver;"> </span><span style="color: green;">We're</span><span style="color: silver;"> </span><span style="color: green;">keeping</span><span style="color: silver;"> </span><span style="color: green;">30-bit</span><span style="color: silver;"> </span><span style="color: green;">fidelity.</span></b>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setLive</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">live)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(live</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: maroon;">m_live</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">live;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_item</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">.isNull()))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.clear();</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>scheduleUpdate</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_grab</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_dirtyTexture</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">emit</span><span style="color: silver;"> </span><span style="color: black;">updateRequested();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setRecursive</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">recursive)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_recursive</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">recursive;</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setMirrorHorizontal</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">mirror)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">mirror;</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>setMirrorVertical</i></span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">mirror)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">mirror;</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_live</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_grab</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">emit</span><span style="color: silver;"> </span><span style="color: black;">updateRequested();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::grab()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_item</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">.isNull())</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.clear();</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*root</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_item</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">while</span><span style="color: silver;"> </span><span style="color: black;">(root->firstChild()</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">root->type()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: black;">::</span><span style="color: purple;">RootNodeType</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">root</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">root->firstChild();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(root->type()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: black;">::</span><span style="color: purple;">RootNodeType</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_renderer</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">-></span><span style="color: black;"><i>createRenderer</i></span><span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: black;">connect(</span><span style="color: maroon;">m_renderer</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: olive;">SIGNAL</span><span style="color: black;">(</span>sceneGraphChanged<span style="color: black;">()),</span><span style="color: silver;"> </span><span style="color: olive;">this</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: olive;">SLOT</span><span style="color: black;">(</span>markDirtyTexture<span style="color: black;">()));</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setDevicePixelRatio(</span><span style="color: maroon;">m_device_pixel_ratio</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setRootNode(</span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: purple;">QSGRootNode</span><span style="color: silver;"> </span><span style="color: black;">*>(root));</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::currentContext()->functions();</span>
<span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">deleteFboLater</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->size()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->format().internalTextureFormat()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span>
<span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_fbo</span><span style="color: black;">->format().mipmap()</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmap</span><span style="color: black;">))</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_multisamplingChecked</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_context</span><span style="color: black;">->openglContext()->format().samples()</span><span style="color: silver;"> </span><span style="color: black;"><=</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_multisampling</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSet</span><span style="color: black;"><</span><span style="color: purple;">QByteArray</span><span style="color: black;">></span><span style="color: silver;"> </span><span style="color: black;">extensions</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">->openglContext()->extensions();</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_multisampling</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">extensions.contains(</span><span style="color: navy;">QByteArrayLiteral</span><span style="color: black;">(</span><span style="color: green;">"GL_EXT_framebuffer_multisample"</span><span style="color: black;">))</span>
<span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">extensions.contains(</span><span style="color: navy;">QByteArrayLiteral</span><span style="color: black;">(</span><span style="color: green;">"GL_EXT_framebuffer_blit"</span><span style="color: black;">));</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_multisamplingChecked</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_multisampling</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Don't</span><span style="color: silver;"> </span><span style="color: green;">delete</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">FBO</span><span style="color: silver;"> </span><span style="color: green;">right</span><span style="color: silver;"> </span><span style="color: green;">away</span><span style="color: silver;"> </span><span style="color: green;">in</span><span style="color: silver;"> </span><span style="color: green;">case</span><span style="color: silver;"> </span><span style="color: green;">it</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">used</span><span style="color: silver;"> </span><span style="color: green;">recursively.</span>
<span style="color: silver;"> </span><span style="color: black;">deleteFboLater</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObjectFormat</span><span style="color: silver;"> </span><span style="color: black;">format;</span>
<span style="color: silver;"> </span><span style="color: black;">format.setInternalTextureFormat(</span><span style="color: maroon;">m_format</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setSamples(</span><span style="color: maroon;">m_context</span><span style="color: black;">->openglContext()->format().samples());</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">-></span><span style="color: black;"><i>depthStencilBufferForFbo</i></span><span style="color: black;">(</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObjectFormat</span><span style="color: silver;"> </span><span style="color: black;">format;</span>
<span style="color: silver;"> </span><span style="color: black;">format.setInternalTextureFormat(</span><span style="color: maroon;">m_format</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setMipmap(</span><span style="color: maroon;">m_mipmap</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_recursive</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">deleteFboLater</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format);</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">->texture());</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions(</span><span style="color: olive;">true</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">-></span><span style="color: black;"><i>depthStencilBufferForFbo</i></span><span style="color: black;">(</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->texture());</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions(</span><span style="color: olive;">true</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_context</span><span style="color: black;">-></span><span style="color: black;"><i>depthStencilBufferForFbo</i></span><span style="color: black;">(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_recursive</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">!</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">m_fbo</span><span style="color: silver;"> </span><span style="color: green;">already</span><span style="color: silver;"> </span><span style="color: green;">created,</span><span style="color: silver;"> </span><span style="color: green;">m_recursive</span><span style="color: silver;"> </span><span style="color: green;">was</span><span style="color: silver;"> </span><span style="color: green;">just</span><span style="color: silver;"> </span><span style="color: green;">set.</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_ASSERT</span><span style="color: black;">(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_ASSERT</span><span style="color: black;">(!</span><span style="color: maroon;">m_multisampling</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->format());</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">->texture());</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions(</span><span style="color: olive;">true</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Render</span><span style="color: silver;"> </span><span style="color: green;">texture.</span>
<span style="color: silver;"> </span><span style="color: black;">root->markDirty(</span><span style="color: purple;">QSGNode</span><span style="color: black;">::</span><span style="color: purple;">DirtyForceUpdate</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Force</span><span style="color: silver;"> </span><span style="color: green;">matrix,</span><span style="color: silver;"> </span><span style="color: green;">clip</span><span style="color: silver;"> </span><span style="color: green;">and</span><span style="color: silver;"> </span><span style="color: green;">opacity</span><span style="color: silver;"> </span><span style="color: green;">update.</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">-></span><span style="color: black;"><i>nodeChanged</i></span><span style="color: black;">(root,</span><span style="color: silver;"> </span><span style="color: purple;">QSGNode</span><span style="color: black;">::</span><span style="color: purple;">DirtyForceUpdate</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Force</span><span style="color: silver;"> </span><span style="color: green;">render</span><span style="color: silver;"> </span><span style="color: green;">list</span><span style="color: silver;"> </span><span style="color: green;">update.</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span>qmlFboOverlay<span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QSGSimpleRectNode</span><span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">->setRect(</span><span style="color: purple;">QRectF</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">.width(),</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">.height()));</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">->setColor(</span><span style="color: purple;">QColor</span><span style="color: black;">(</span><span style="color: navy;">0xff</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0x00</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0x80</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0x40</span><span style="color: black;">));</span>
<span style="color: silver;"> </span><span style="color: black;">root->appendChildNode(</span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_dirtyTexture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setDeviceRect(</span><span style="color: maroon;">m_size</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setViewportRect(</span><span style="color: maroon;">m_size</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: black;">mirrored(</span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.right()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.left(),</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.bottom()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.top(),</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: maroon;">m_rect</span><span style="color: black;">.width()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.width(),</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: maroon;">m_rect</span><span style="color: black;">.height()</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_rect</span><span style="color: black;">.height());</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setProjectionMatrixToRect(mirrored);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">->setClearColor(</span><span style="color: purple;">Qt</span><span style="color: black;">::</span><span style="color: purple;">transparent</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_multisampling</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">-></span><span style="color: black;"><i>renderScene</i></span><span style="color: black;">(</span><span style="color: purple;">BindableFbo</span><span style="color: black;">(</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.data()));</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(deleteFboLater)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObjectFormat</span><span style="color: silver;"> </span><span style="color: black;">format;</span>
<span style="color: silver;"> </span><span style="color: black;">format.setInternalTextureFormat(</span><span style="color: maroon;">m_format</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setAttachment(</span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">::</span><span style="color: purple;">NoAttachment</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setMipmap(</span><span style="color: maroon;">m_mipmap</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setSamples(</span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format);</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->texture());</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions(</span><span style="color: olive;">true</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: purple;">QRect</span><span style="color: silver;"> </span><span style="color: black;">r(</span><span style="color: purple;">QPoint</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: maroon;">m_size</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">::blitFramebuffer(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">r,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">r);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_recursive</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">-></span><span style="color: black;"><i>renderScene</i></span><span style="color: black;">(</span><span style="color: purple;">BindableFbo</span><span style="color: black;">(</span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.data()));</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(deleteFboLater)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObjectFormat</span><span style="color: silver;"> </span><span style="color: black;">format;</span>
<span style="color: silver;"> </span><span style="color: black;">format.setAttachment(</span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">::</span><span style="color: purple;">CombinedDepthStencil</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setInternalTextureFormat(</span><span style="color: maroon;">m_format</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">format.setMipmap(</span><span style="color: maroon;">m_mipmap</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFramebufferObject</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format);</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->texture());</span>
<span style="color: silver;"> </span><span style="color: black;">updateBindOptions(</span><span style="color: olive;">true</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">qSwap(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_secondaryFbo</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_renderer</span><span style="color: black;">-></span><span style="color: black;"><i>renderScene</i></span><span style="color: black;">(</span><span style="color: purple;">BindableFbo</span><span style="color: black;">(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthStencilBuffer</span><span style="color: black;">.data()));</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_mipmap</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glBindTexture(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;"><i>textureId</i></span><span style="color: black;">());</span>
<span style="color: silver;"> </span><span style="color: black;">funcs->glGenerateMipmap(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">root->markDirty(</span><span style="color: purple;">QSGNode</span><span style="color: black;">::</span><span style="color: purple;">DirtyForceUpdate</span><span style="color: black;">);</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Force</span><span style="color: silver;"> </span><span style="color: green;">matrix,</span><span style="color: silver;"> </span><span style="color: green;">clip,</span><span style="color: silver;"> </span><span style="color: green;">opacity</span><span style="color: silver;"> </span><span style="color: green;">and</span><span style="color: silver;"> </span><span style="color: green;">render</span><span style="color: silver;"> </span><span style="color: green;">list</span><span style="color: silver;"> </span><span style="color: green;">update.</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: navy;">QSG_DEBUG_FBO_OVERLAY</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span>qmlFboOverlay<span style="color: black;">())</span>
<span style="color: silver;"> </span><span style="color: black;">root->removeChildNode(</span><span style="color: maroon;">m_debugOverlay</span><span style="color: black;">);</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_recursive</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;"><i>markDirtyTexture</i></span><span style="color: black;">();</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Continuously</span><span style="color: silver;"> </span><span style="color: green;">update</span><span style="color: silver;"> </span><span style="color: green;">if</span><span style="color: silver;"> </span><span style="color: green;">'live'</span><span style="color: silver;"> </span><span style="color: green;">and</span><span style="color: silver;"> </span><span style="color: green;">'recursive'.</span>
<span style="color: black;">}</span>
<span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>toImage</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_fbo</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_fbo</span><span style="color: black;">->toImage();</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGLayer</span><span style="color: black;">::</span><span style="color: black;"><i>normalizedTextureSubRect</i></span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: black;">(</span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorHorizontal</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: navy;">1</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_mirrorVertical</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: navy;">1</span><span style="color: black;">);</span>
<span style="color: black;">}</span>
<span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;"><qtquick private="" qsgdepthstencilbuffer_p.h=""></qtquick></span>
<span style="color: navy;">QT_BEGIN_NAMESPACE</span>
<span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::QSGDepthStencilBuffer(</span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*context,</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">Format</span><span style="color: silver;"> </span><span style="color: black;">&format)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">(context)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_manager</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_format</span><span style="color: black;">(format)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">'m_manager'</span><span style="color: silver;"> </span><span style="color: green;">is</span><span style="color: silver;"> </span><span style="color: green;">set</span><span style="color: silver;"> </span><span style="color: green;">by</span><span style="color: silver;"> </span><span style="color: green;">QSGDepthStencilBufferManager::insertBuffer().</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::~</span><span style="color: black;"><i>QSGDepthStencilBuffer</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_manager</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_manager</span><span style="color: black;">-></span><span style="color: maroon;">m_buffers</span><span style="color: black;">.remove(</span><span style="color: maroon;">m_format</span><span style="color: black;">);</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::attach()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glFramebufferRenderbuffer(</span><span style="color: navy;">GL_FRAMEBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_ATTACHMENT</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glFramebufferRenderbuffer(</span><span style="color: navy;">GL_FRAMEBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_STENCIL_ATTACHMENT</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: black;">);</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::detach()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glFramebufferRenderbuffer(</span><span style="color: navy;">GL_FRAMEBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_ATTACHMENT</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glFramebufferRenderbuffer(</span><span style="color: navy;">GL_FRAMEBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_STENCIL_ATTACHMENT</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: black;">}</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span>GL_DEPTH24_STENCIL8_OES
<span style="color: navy;">#define</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH24_STENCIL8_OES</span><span style="color: silver;"> </span><span style="color: navy;">0x88F0</span>
<span style="color: navy;">#endif</span>
<span style="color: navy;">#ifndef</span><span style="color: silver;"> </span>GL_DEPTH_COMPONENT24_OES
<span style="color: navy;">#define</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_COMPONENT24_OES</span><span style="color: silver;"> </span><span style="color: navy;">0x81A6</span>
<span style="color: navy;">#endif</span>
<span style="color: purple;">QSGDefaultDepthStencilBuffer</span><span style="color: black;">::QSGDefaultDepthStencilBuffer(</span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*context,</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">Format</span><span style="color: silver;"> </span><span style="color: black;">&format)</span>
<span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">(context,</span><span style="color: silver;"> </span><span style="color: black;">format)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">GLsizei</span><span style="color: silver;"> </span><span style="color: black;">width</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">size</span><span style="color: black;">.width();</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">GLsizei</span><span style="color: silver;"> </span><span style="color: black;">height</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">size</span><span style="color: black;">.height();</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">attachments</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: purple;">DepthAttachment</span><span style="color: silver;"> </span><span style="color: black;">|</span><span style="color: silver;"> </span><span style="color: purple;">StencilAttachment</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.hasOpenGLExtension(</span><span style="color: purple;">QOpenGLExtensions</span><span style="color: black;">::</span><span style="color: purple;">PackedDepthStencil</span><span style="color: black;">))</span>
<span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glGenRenderbuffers(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glBindRenderbuffer(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">samples</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.hasOpenGLExtension(</span><span style="color: purple;">QOpenGLExtensions</span><span style="color: black;">::</span><span style="color: purple;">FramebufferMultisample</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: navy;">#if</span><span style="color: silver;"> </span>defined<span style="color: black;">(</span>QT_OPENGL_ES_2<span style="color: black;">)</span>
<span style="color: silver;"> </span>m_functions<span style="color: black;">.</span>glRenderbufferStorageMultisample<span style="color: black;">(</span>GL_RENDERBUFFER<span style="color: black;">,</span><span style="color: silver;"> </span>format<span style="color: black;">.</span>samples<span style="color: black;">,</span>
<span style="color: silver;"> </span>GL_DEPTH24_STENCIL8_OES<span style="color: black;">,</span><span style="color: silver;"> </span>width<span style="color: black;">,</span><span style="color: silver;"> </span>height<span style="color: black;">);</span>
<span style="color: navy;">#else</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorageMultisample(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">samples</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH24_STENCIL8</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: navy;">#if</span><span style="color: silver;"> </span>defined<span style="color: black;">(</span>QT_OPENGL_ES_2<span style="color: black;">)</span>
<span style="color: silver;"> </span>m_functions<span style="color: black;">.</span>glRenderbufferStorage<span style="color: black;">(</span>GL_RENDERBUFFER<span style="color: black;">,</span><span style="color: silver;"> </span>GL_DEPTH24_STENCIL8_OES<span style="color: black;">,</span><span style="color: silver;"> </span>width<span style="color: black;">,</span><span style="color: silver;"> </span>height<span style="color: black;">);</span>
<span style="color: navy;">#else</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorage(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH24_STENCIL8</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_depthBuffer</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">attachments</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">DepthAttachment</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glGenRenderbuffers(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glBindRenderbuffer(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_COMPONENT</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(context->isOpenGLES())</span>
<span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.hasOpenGLExtension(</span><span style="color: purple;">QOpenGLExtensions</span><span style="color: black;">::</span><span style="color: purple;">Depth24</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_COMPONENT24_OES</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">GL_DEPTH_COMPONENT16</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">samples</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.hasOpenGLExtension(</span><span style="color: purple;">QOpenGLExtensions</span><span style="color: black;">::</span><span style="color: purple;">FramebufferMultisample</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorageMultisample(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">samples</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: black;">internalFormat,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorage(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">internalFormat,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_stencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">attachments</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: purple;">StencilAttachment</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glGenRenderbuffers(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_stencilBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glBindRenderbuffer(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: black;">);</span>
<span style="color: navy;">#ifdef</span><span style="color: silver;"> </span><span style="color: purple;">QT_OPENGL_ES</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span>GLenum<span style="color: silver;"> </span>internalFormat<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span>GL_STENCIL_INDEX8<span style="color: black;">;</span>
<span style="color: navy;">#else</span>
<span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">GLenum</span><span style="color: silver;"> </span><span style="color: black;">internalFormat</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">context->isOpenGLES()</span><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: navy;">GL_STENCIL_INDEX8</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">GL_STENCIL_INDEX</span><span style="color: black;">;</span>
<span style="color: navy;">#endif</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(format.</span><span style="color: maroon;">samples</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.hasOpenGLExtension(</span><span style="color: purple;">QOpenGLExtensions</span><span style="color: black;">::</span><span style="color: purple;">FramebufferMultisample</span><span style="color: black;">))</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorageMultisample(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">samples</span><span style="color: black;">,</span>
<span style="color: silver;"> </span><span style="color: black;">internalFormat,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glRenderbufferStorage(</span><span style="color: navy;">GL_RENDERBUFFER</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">internalFormat,</span><span style="color: silver;"> </span><span style="color: black;">width,</span><span style="color: silver;"> </span><span style="color: black;">height);</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGDefaultDepthStencilBuffer</span><span style="color: black;">::~</span><span style="color: black;"><i>QSGDefaultDepthStencilBuffer</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: black;"><i>free</i></span><span style="color: black;">();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QSGDefaultDepthStencilBuffer</span><span style="color: black;">::</span><span style="color: black;"><i>free</i></span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glDeleteRenderbuffers(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_stencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: black;">)</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_functions</span><span style="color: black;">.glDeleteRenderbuffers(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_stencilBuffer</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_depthBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_stencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSGDepthStencilBufferManager</span><span style="color: black;">::~</span><span style="color: purple;">QSGDepthStencilBufferManager</span><span style="color: black;">()</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: purple;">Hash</span><span style="color: black;">::</span><span style="color: purple;">const_iterator</span><span style="color: silver;"> </span><span style="color: black;">it</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_buffers</span><span style="color: black;">.constBegin(),</span><span style="color: silver;"> </span><span style="color: black;">cend</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_buffers</span><span style="color: black;">.constEnd();</span><span style="color: silver;"> </span><span style="color: black;">it</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: black;">cend;</span><span style="color: silver;"> </span><span style="color: black;">++it)</span><span style="color: silver;"> </span><span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: silver;"> </span><span style="color: black;">*buffer</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">it.value().data();</span>
<span style="color: silver;"> </span><span style="color: black;">buffer-></span><span style="color: black;"><i>free</i></span><span style="color: black;">();</span>
<span style="color: silver;"> </span><span style="color: black;">buffer-></span><span style="color: maroon;">m_manager</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: black;">}</span>
<span style="color: black;">}</span>
<span style="color: purple;">QSharedPointer</span><span style="color: black;"><</span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">></span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBufferManager</span><span style="color: black;">::bufferForFormat(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::</span><span style="color: purple;">Format</span><span style="color: silver;"> </span><span style="color: black;">&fmt)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: purple;">Hash</span><span style="color: black;">::</span><span style="color: purple;">const_iterator</span><span style="color: silver;"> </span><span style="color: black;">it</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: maroon;">m_buffers</span><span style="color: black;">.constFind(fmt);</span>
<span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(it</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: maroon;">m_buffers</span><span style="color: black;">.constEnd())</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">it.value().toStrongRef();</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: purple;">QSharedPointer</span><span style="color: black;"><</span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">>();</span>
<span style="color: black;">}</span>
<span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBufferManager</span><span style="color: black;">::insertBuffer(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSharedPointer</span><span style="color: black;"><</span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">></span><span style="color: silver;"> </span><span style="color: black;">&buffer)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_ASSERT</span><span style="color: black;">(buffer-></span><span style="color: maroon;">m_manager</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">);</span>
<span style="color: silver;"> </span><span style="color: navy;">Q_ASSERT</span><span style="color: black;">(!</span><span style="color: maroon;">m_buffers</span><span style="color: black;">.contains(buffer-></span><span style="color: maroon;">m_format</span><span style="color: black;">));</span>
<span style="color: silver;"> </span><span style="color: black;">buffer-></span><span style="color: maroon;">m_manager</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">this</span><span style="color: black;">;</span>
<span style="color: silver;"> </span><span style="color: maroon;">m_buffers</span><span style="color: black;">.insert(buffer-></span><span style="color: maroon;">m_format</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">buffer.toWeakRef());</span>
<span style="color: black;">}</span>
<span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: black;">qHash(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSGDepthStencilBuffer</span><span style="color: black;">::</span><span style="color: purple;">Format</span><span style="color: silver;"> </span><span style="color: black;">&format)</span>
<span style="color: black;">{</span>
<span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">qHash(qMakePair(format.</span><span style="color: maroon;">size</span><span style="color: black;">.width(),</span><span style="color: silver;"> </span><span style="color: black;">format.</span><span style="color: maroon;">size</span><span style="color: black;">.height()))</span>
<span style="color: silver;"> </span><span style="color: black;">^</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: purple;">uint</span><span style="color: black;">(format.</span><span style="color: maroon;">samples</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: navy;">12</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">^</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: purple;">uint</span><span style="color: black;">(format.</span><span style="color: maroon;">attachments</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: navy;">28</span><span style="color: black;">);</span>
<span style="color: black;">}</span>
<span style="color: navy;">QT_END_NAMESPACE</span></pre>
<pre class="western"><span style="color: navy;">
</span></pre>
You may note that the body of <span style="font-family: Liberation Mono, monospace;">ThirtyBitSGLayer::setFormat</span>
has been replaced by the comment, <span style="font-family: Liberation Mono, monospace;">NOPE!
We're keeping 30-bit fidelity</span>. This is necessary because the
<span style="font-family: Liberation Mono, monospace;">QObject</span> side of our
<span style="font-family: Liberation Mono, monospace;">ThirtyBitSGLayer</span> class
remains <span style="font-family: Liberation Mono, monospace;">QQuickItemLayer</span>,
and <span style="font-family: Liberation Mono, monospace;">QQuickItemLayer</span>
calls <span style="font-family: Liberation Mono, monospace;">ThirtyBitSGLayer::setFormat</span>
to demand that we revert back to inferior bullshit 24-bit color,
which we don't want to do. So, we don't. Ha!<br />
<br />
It would be more elegant to make <span style="font-family: Liberation Mono, monospace;">QQuickItemLayer</span>
stop being an asshole, but this can only be practically accomplished
by patching and rebuilding Qt: the relevant <span style="font-family: Liberation Mono, monospace;">QQuickItemLayer</span>
instance is created by <span style="font-family: Liberation Mono, monospace;">QQuickItemPrivate</span>,
which can not be modified except by copy/paste/modifying <span style="font-family: Liberation Mono, monospace;">QQuickItem</span>
and all of its associated private classes. By itself, this is
straightforward (we do it with <span style="font-family: Liberation Mono, monospace;">QSGLayer</span>
to make <span style="font-family: Liberation Mono, monospace;">ThirtyBitSGLayer</span>,
after all). However, the <span style="font-family: Liberation Mono, monospace;">QQuickItem</span>
type is referenced directly in a vast number of places within Qt, and
we would have to copy/paste/modify these as well, which would be
immensely more work than simply unfucking <span style="font-family: Liberation Mono, monospace;">QQuickItemLayer</span>'s
definition in the Qt source itself and rebuilding it.<br />
<br />
And, that's it. With this code, 30-bit color works in QML scene
layers.<br />
<br />
The same technique can be used to keep layers in
float32-per-channel format, float64-per-channel format, or whatever
else you need.<br />
<br />
It would be outstanding if Qt's QML stuff eventually provides a
simple way of controlling layer formats without resorting to the
private API and generally wasting many developer days <i>each and
every time</i> someone needs it. However, the same was true for
QtWidgets, and it never happened. So, I doubt this will ever be
improved, either.<br />
<br />
<br />
It's probably too hard; the Qt developers simply are not up to the
challenge. ;-)Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com1tag:blogger.com,1999:blog-4636329550025284673.post-44870462272441084522015-12-23T10:06:00.003+01:002015-12-27T06:56:27.445+01:00Doing anything significant whatsoever with QML, part 4: 30-bit color QQuickFramebufferObject support (continued)Returning a custom <span style="font-family: Courier New, Courier, monospace;">QSGNode</span> from <span style="font-family: Courier New, Courier, monospace;">ThirtyBitImageItem</span>'s <span style="background-color: white; font-family: 'Courier New', Courier, monospace; font-size: 19px;">QuickImage::updatePaintNode </span>seems like the most promising approach. Rather than attempting to add functionality to the <span style="font-family: Courier New, Courier, monospace;">QQuickImage</span> class, which is part of Qt's private API, it may be sufficient to derive my own implementation of <span style="font-family: Courier New, Courier, monospace;">QSGTexture</span> and return that from <span style="background-color: white; font-family: 'Courier New', Courier, monospace; font-size: 19px;">QuickImage::updatePaintNode</span>!<br />
<div>
<br /></div>
<div>
<strike>I arrived at this approach after applying a <a href="https://codereview.qt-project.org/#/c/111779/">patch set that adds 16-bpc support to <span style="font-family: Courier New, Courier, monospace;">QImage</span></a>. (I had to do a bit of development to bring these patches up to date for applying against Qt 5.6.0-beta1). The patch set does not address QML, so I started in on the work required to make QML use 16-bpc <span style="font-family: Courier New, Courier, monospace;">QImage</span>s when advantageous, at which point I noticed that the internal format of QML <span style="font-family: Courier New, Courier, monospace;">SGDefaultLayer</span> textures is always specified as unsized (<span style="font-family: Courier New, Courier, monospace;">GL_RGBA</span>), and storage of texture data in a <span style="font-family: Courier New, Courier, monospace;">QImage</span> only occurs when necessary. It's necessary only when pulling pixel data from the GPU, which is comparatively slow and not done unless explicitly demanded. Thus, the possibility exists that I can put 10-bpc texture data into the QML scene graph pipeline without losing fidelity or sacrificing alpha channel depth. Furthermore, <span style="font-family: Courier New, Courier, monospace;">QImage</span> does have native 10-bpc support, even without the 16-bpc patches. Even rendering a <span style="font-family: Courier New, Courier, monospace;">QQuickWindow</span> to a 10-bpc <span style="font-family: Courier New, Courier, monospace;">QImage</span> should be possible, though loss of alpha depth can not be avoided when doing so.</strike></div>
<div>
<br /></div>
<div>
The previous paragraph turned out to be incorrect; <span style="font-family: Courier New, Courier, monospace;">glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA ...)</span> yields a texture with 8-bpc fidelity. So, simply returning a real 30-bit texture from <span style="font-family: Courier New, Courier, monospace;">::updatePaintNode</span> is not sufficient for retaining 30-bit fidelity with <span style="font-family: Courier New, Courier, monospace;">layer.enabled = true</span>. We are going to have to derive and implement more stuff in order to have 30-bit items fully participate in a QML scene, and this will inevitably require 30-bit <span style="font-family: Courier New, Courier, monospace;">QSGTexture</span>s.<br />
<br />
However, simply attaching an instance of our 30-bit <span style="font-family: Courier New, Courier, monospace;">QSGTexture</span> derivative to a <span style="font-family: Courier New, Courier, monospace;">QSGSimpleTextureNode</span> returned from <span style="font-family: Courier New, Courier, monospace;">::updatePaintNode</span> does preserve 30-bit fidelity. <a href="https://github.com/erikhvatum/StackStream/tree/e2612842fab39309db47118cedf37b045708a15d">The relevant code</a>:<br />
<br />
<i>ThirtyBitSGTexture.h:</i><br />
<i><br /></i>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#pragma</span><span style="color: silver;"> </span>once</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"common.h"</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: navy;">Q_OBJECT</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">public</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">virtual</span><span style="color: silver;"> </span><span style="color: black;">~</span><span style="color: black; font-style: italic;">ThirtyBitSGTexture</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setOwnsTexture</span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">owns</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">owns</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">ownsTexture</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setTextureId</span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span>id<span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">textureId</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setTextureSize</span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">size</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">size</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">textureSize</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setHasAlphaChannel</span><span style="color: black;">(</span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">alpha</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">alpha</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">hasAlphaChannel</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">hasMipmaps</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">mipmapFiltering</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span><span style="color: black;">::</span><span style="color: purple;">None</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setImage</span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">&</span>image<span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">image</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">{</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: black;">;</span><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">virtual</span><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">bind</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">static</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">fromImage</span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">image</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">t</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">t</span><span style="color: black;">-></span><span style="color: black;">setImage</span><span style="color: black;">(</span><span style="color: black;">image</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">t</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">protected</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">GLuint</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_rect</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_texture</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">uint</span><span style="color: silver;"> </span><span style="color: maroon;">m_retain_image</span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">};</span></span></pre>
<br />
<pre>
<!--EndFragment--></pre>
<br />
<i>ThirtyBitSGTexture.cpp:</i><br />
<i><br /></i>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"common.h"</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">"ThirtyBitSGTexture.h"</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQml/private/qqmlglobal_p.h></span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qquickprofiler_p.h></span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgcontext_p.h></span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgmaterialshader_p.h></span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: navy;">#include</span><span style="color: silver;"> </span><span style="color: green;">< QtQuick/private/qsgtexture_p.h></span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">inline</span><span style="color: silver;"> </span><span style="color: olive;">static</span><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: black;">isPowerOfTwo</span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;">x</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Assumption:</span><span style="color: silver;"> </span><span style="color: green;">x</span><span style="color: silver;"> </span><span style="color: green;">>=</span><span style="color: silver;"> </span><span style="color: green;">1</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">x</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">x</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: black;">-</span><span style="color: black;">x</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::</span><span style="color: black;">ThirtyBitSGTexture</span><span style="color: black;">()</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span><span style="color: black;">()</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_texture</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: black;">(</span><span style="color: olive;">true</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_retain_image</span><span style="color: black;">(</span><span style="color: olive;">false</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::~</span><span style="color: black; font-style: italic;">ThirtyBitSGTexture</span><span style="color: black;">()</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">())</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">()-></span><span style="color: black;">functions</span><span style="color: black;">()-></span><span style="color: black;">glDeleteTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::</span><span style="color: black;">setImage</span><span style="color: black;">(</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: black;">image</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">size</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">.</span><span style="color: black;">hasAlphaChannel</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_texture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::</span><span style="color: black; font-style: italic;">textureId</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_dirty_texture</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_image</span><span style="color: black;">.</span><span style="color: black;">isNull</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">The</span><span style="color: silver;"> </span><span style="color: green;">actual</span><span style="color: silver;"> </span><span style="color: green;">texture</span><span style="color: silver;"> </span><span style="color: green;">and</span><span style="color: silver;"> </span><span style="color: green;">id</span><span style="color: silver;"> </span><span style="color: green;">will</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">updated/deleted</span><span style="color: silver;"> </span><span style="color: green;">in</span><span style="color: silver;"> </span><span style="color: green;">a</span><span style="color: silver;"> </span><span style="color: green;">later</span><span style="color: silver;"> </span><span style="color: green;">bind()</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">or</span><span style="color: silver;"> </span><span style="color: green;">~ThirtyBitSGTexture</span><span style="color: silver;"> </span><span style="color: green;">so</span><span style="color: silver;"> </span><span style="color: green;">just</span><span style="color: silver;"> </span><span style="color: green;">keep</span><span style="color: silver;"> </span><span style="color: green;">it</span><span style="color: silver;"> </span><span style="color: green;">minimal</span><span style="color: silver;"> </span><span style="color: green;">here.</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span><span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">){</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Generate</span><span style="color: silver;"> </span><span style="color: green;">a</span><span style="color: silver;"> </span><span style="color: green;">texture</span><span style="color: silver;"> </span><span style="color: green;">id</span><span style="color: silver;"> </span><span style="color: green;">for</span><span style="color: silver;"> </span><span style="color: green;">use</span><span style="color: silver;"> </span><span style="color: green;">later</span><span style="color: silver;"> </span><span style="color: green;">and</span><span style="color: silver;"> </span><span style="color: green;">return</span><span style="color: silver;"> </span><span style="color: green;">it.</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">()-></span><span style="color: black;">functions</span><span style="color: black;">()-></span><span style="color: black;">glGenTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: olive;">const_cast</span><span style="color: black;"><</span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: silver;"> </span><span style="color: black;">*>(</span><span style="color: olive;">this</span><span style="color: black;">)-></span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::</span><span style="color: black;">setTextureId</span><span style="color: black;">(</span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: black;">id</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">()-></span><span style="color: black;">functions</span><span style="color: black;">()-></span><span style="color: black;">glDeleteTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">id</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_texture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitSGTexture</span><span style="color: black;">::</span><span style="color: black; font-style: italic;">bind</span><span style="color: black;">()</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">context</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QOpenGLContext</span><span style="color: black;">::</span><span style="color: black;">currentContext</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QOpenGLFunctions</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">funcs</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">context</span><span style="color: black;">-></span><span style="color: black;">functions</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_dirty_texture</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBindTexture</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">mipmapFiltering</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span><span style="color: black;">::</span><span style="color: purple;">None</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: black;">!</span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glGenerateMipmap</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">updateBindOptions</span><span style="color: black;">(</span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_texture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_image</span><span style="color: black;">.</span><span style="color: black;">isNull</span><span style="color: black;">())</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">&&</span><span style="color: silver;"> </span><span style="color: maroon;">m_owns_texture</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glDeleteTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QSize</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_has_alpha</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_texture_id</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glGenTextures</span><span style="color: black;">(</span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">&</span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glBindTexture</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_id</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">tmp</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: maroon;">m_image</span><span style="color: black;">.</span><span style="color: black;">format</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_RGB30</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: black;">.</span><span style="color: black;">format</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">==</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_A2RGB30_Premultiplied</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">?</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: black;">.</span><span style="color: black;">convertToFormat</span><span style="color: black;">(</span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_A2RGB30_Premultiplied</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">tmp</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: black;">tmp</span><span style="color: black;">.</span><span style="color: black;">bytesPerLine</span><span style="color: black;">())</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">tmp</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">tmp</span><span style="color: black;">.</span><span style="color: black;">copy</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">updateBindOptions</span><span style="color: black;">(</span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glTexImage2D</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_RGB10_A2</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: black;">.</span><span style="color: black;">width</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: maroon;">m_texture_size</span><span style="color: black;">.</span><span style="color: black;">height</span><span style="color: black;">(),</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_BGRA</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">GL_UNSIGNED_INT_2_10_10_10_REV</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: black;">tmp</span><span style="color: black;">.</span><span style="color: black;">constBits</span><span style="color: black;">());</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">mipmapFiltering</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;">!=</span><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span><span style="color: black;">::</span><span style="color: purple;">None</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">funcs</span><span style="color: black;">-></span><span style="color: black;">glGenerateMipmap</span><span style="color: black;">(</span><span style="color: navy;">GL_TEXTURE_2D</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_mipmaps_generated</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_texture_rect</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QRectF</span><span style="color: black;">(</span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: navy;">1</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_dirty_bind_options</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">false</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: maroon;">m_retain_image</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></pre>
<br />
<pre>
</pre>
<span style="font-family: Courier New, Courier, monospace;">Image::as10BpcQImage() const definition from </span><i>Image.cpp</i>:<br />
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: purple;">Image</span><span style="color: black;">::</span><span style="color: black;">as10BpcQImage</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: black;">(!</span><span style="color: maroon;">m_isValid</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint8_t</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">fiPixIt</span><span style="color: black;">{</span><span style="color: olive;">reinterpret_cast</span><span style="color: black;"><</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint8_t</span><span style="color: black;">*>(</span><span style="color: maroon;">m_rawData</span><span style="color: black;">.</span><span style="color: black;">get</span><span style="color: black;">())};</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint8_t</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: black;">fiPixEndIt</span><span style="color: black;">{</span><span style="color: black;">fiPixIt</span><span style="color: silver;"> </span><span style="color: black;">+</span><span style="color: silver;"> </span><span style="color: maroon;">m_byteCount</span><span style="color: black;">};</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint8_t</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">qiPixIt</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: silver;"> </span><span style="color: black;">ret</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: black;">aFactor</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">switch</span><span style="color: black;">(</span><span style="color: maroon;">m_channelCount</span><span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">default</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: navy;">qWarning</span><span style="color: black;">(</span><span style="color: green;">"m_channelCount</span><span style="color: silver;"> </span><span style="color: green;">must</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">4."</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">ret</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">(</span><span style="color: maroon;">m_size</span><span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: purple;">QImage</span><span style="color: black;">::</span><span style="color: purple;">Format_A2RGB30_Premultiplied</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">qiPixIt</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">ret</span><span style="color: black;">.</span><span style="color: black;">bits</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: black;">(;;)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">FIRGBA16</span><span style="color: black;">&</span><span style="color: silver;"> </span><span style="color: black;">fiPix</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: olive;">reinterpret_cast</span><span style="color: black;"><</span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">FIRGBA16</span><span style="color: black;">*>(</span><span style="color: black;">fiPixIt</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">aFactor</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: olive;">float</span><span style="color: black;">>(</span><span style="color: black;">fiPix</span><span style="color: black;">.</span><span style="color: maroon;">alpha</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">/</span><span style="color: silver;"> </span><span style="color: navy;">0xffff</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Should</span><span style="color: silver;"> </span><span style="color: green;">be</span><span style="color: silver;"> </span><span style="color: green;">endian</span><span style="color: silver;"> </span><span style="color: green;">safe</span><span style="color: silver;"> </span><span style="color: green;">(not</span><span style="color: silver;"> </span><span style="color: green;">tested</span><span style="color: silver;"> </span><span style="color: green;">on</span><span style="color: silver;"> </span><span style="color: green;">big</span><span style="color: silver;"> </span><span style="color: green;">endian,</span><span style="color: silver;"> </span><span style="color: green;">however)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: olive;">reinterpret_cast</span><span style="color: black;"><</span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint32_t</span><span style="color: black;">*>(</span><span style="color: black;">qiPixIt</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">=</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">((</span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint32_t</span><span style="color: black;">>(</span><span style="color: black;">fiPix</span><span style="color: black;">.</span><span style="color: maroon;">alpha</span><span style="color: silver;"> </span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">>></span><span style="color: silver;"> </span><span style="color: navy;">14</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: navy;">30</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">|</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">((</span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint32_t</span><span style="color: black;">>(</span><span style="color: black;">fiPix</span><span style="color: black;">.</span><span style="color: maroon;">red</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">aFactor</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">>></span><span style="color: silver;"> </span><span style="color: navy;">6</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: navy;">20</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">|</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">((</span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint32_t</span><span style="color: black;">>(</span><span style="color: black;">fiPix</span><span style="color: black;">.</span><span style="color: maroon;">green</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">aFactor</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">>></span><span style="color: silver;"> </span><span style="color: navy;">6</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;"><<</span><span style="color: silver;"> </span><span style="color: navy;">10</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">|</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: olive;">static_cast</span><span style="color: black;"><</span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">uint32_t</span><span style="color: black;">>(</span><span style="color: black;">fiPix</span><span style="color: black;">.</span><span style="color: maroon;">blue</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">aFactor</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">>></span><span style="color: silver;"> </span><span style="color: navy;">6</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">fiPixIt</span><span style="color: silver;"> </span><span style="color: black;">+=</span><span style="color: silver;"> </span><span style="color: navy;">8</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: black;">(</span><span style="color: black;">fiPixIt</span><span style="color: silver;"> </span><span style="color: black;">>=</span><span style="color: silver;"> </span><span style="color: black;">fiPixEndIt</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">qiPixIt</span><span style="color: silver;"> </span><span style="color: black;">+=</span><span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">break</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}}</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">ret</span><span style="color: black;">;</span></span></pre>
<br />
<pre><span style="font-family: Courier New, Courier, monospace;">}</span><!--EndFragment--></pre>
<br />
Next up: making our own <span style="font-family: Courier New, Courier, monospace;">QSGMaterialNode</span> and/or <span style="font-family: Courier New, Courier, monospace;">QSGLayer</span>, etc, in order to preserve 30-bit fidelity with <span style="font-family: Courier New, Courier, monospace;">layer.enabled = true</span>.</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-56669772073979904262015-12-20T02:43:00.001+01:002015-12-21T08:53:34.088+01:00Doing anything significant whatsoever with QML, part 3: 30-bit color QQuickFramebufferObject supportMy 30-bit <span style="font-family: "courier new" , "courier" , monospace;">QQuickFramebufferObject</span>-derived Layer class (exposed to QML as SSLayer) renders 30-bit color correctly only when blitting directly to the framebuffer of the <span style="font-family: "courier new" , "courier" , monospace;">QQuickWindow</span> that ultimately contains the <span style="font-family: "courier new" , "courier" , monospace;">SSLayer</span>. Using the <span style="font-family: "courier new" , "courier" , monospace;">SSLayer</span> as a <span style="font-family: "courier new" , "courier" , monospace;">ShaderEffectSource</span>, setting <span style="font-family: "courier new" , "courier" , monospace;">SSLayer</span>'s <span style="font-family: "courier new" , "courier" , monospace;">layer.enabled</span> property to true, or otherwise causing <span style="font-family: "courier new" , "courier" , monospace;">SSLayer</span> to be blitted into a texture node results in 8-bit-per-channel re-sampling. Which is fucking unacceptable - <span style="font-family: "courier new" , "courier" , monospace;">SSLayer</span> needs to both participate in the QML scene graph as a fully-fledged blendable, transformable, shade-able scene graph node <i>and</i> retain 30-bit fidelity when doing so. Therefore, if this limitation can not be overcome in a reasonable way, I am going to <i style="font-weight: bold;">forget that QML ever existed.</i><br />
<div>
<br /></div>
<div>
That being the case, let's get started.</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSSuy4LMxVrvBhUF_dAEKweFgJkEGEjq8kViuywGh5eQYV3t_rPZb3sfnJu9WZi-aSZy68yUkV4m4_hXRLbH62ohcEJPSnKJTD-GB_QWFlQOh4eiDsXzNDHZe_VkGBNi7oo3kDSGBIsg/s1600/Neuralizer1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSSuy4LMxVrvBhUF_dAEKweFgJkEGEjq8kViuywGh5eQYV3t_rPZb3sfnJu9WZi-aSZy68yUkV4m4_hXRLbH62ohcEJPSnKJTD-GB_QWFlQOh4eiDsXzNDHZe_VkGBNi7oo3kDSGBIsg/s320/Neuralizer1.png" width="263" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Whoa! Not so fast; this may not be completely hopeless. The Qt docs insist that the QML scene graph is very flexible. We'll see...<br />
<br />
Firstly, <span style="font-family: "courier new" , "courier" , monospace;">QQuickFramebufferObject</span> has a lot of moving parts, and some non-moving parts. <span style="font-family: "courier new" , "courier" , monospace;">QQuickFramebufferObject::textureProvider()</span>, for example, as far as I can tell, is never called. Instead, <span style="font-family: "courier new" , "courier" , monospace;">QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)</span> is responsible for instantiating <span style="font-family: "courier new" , "courier" , monospace;">QSGFramebufferObjectNode</span>, which is a private class defined in <i>qt5/qtdeclarative/src/quick/items/qquickframebufferobject.cpp</i>. So, let's start with making a QML Item (QQuickItem, in C++ land) that does nothing fancy save for rendering to a 30-bit texture when the Item's <span style="font-family: Courier New, Courier, monospace;">layer.enabled</span> property is true.<br />
<br />
In other words, the following, contained in an <span style="font-family: Courier New, Courier, monospace;">ApplicationWindow</span>, should be free of 8-bit banding:<br />
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: purple;">ThirtyBitImageItem</span><span style="color: silver;"> </span>{</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">id</span>:<span style="color: silver;"> </span><span style="color: black; font-style: italic;">thirtyBitImageItem</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">objectName</span>:<span style="color: silver;"> </span><span style="color: green;">"thirtyBitImageItem"</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">anchors.horizontalCenter</span>:<span style="color: silver;"> </span><span style="color: black; font-style: italic;">parent</span>.horizontalCenter</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">anchors.top</span>:<span style="color: silver;"> </span><span style="color: black; font-style: italic;">parent</span>.top</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">anchors.bottom</span>:<span style="color: silver;"> </span><span style="color: black; font-style: italic;">parent</span>.bottom</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">width</span>:<span style="color: silver;"> </span>(<span style="color: black; font-style: italic;">implicitWidth</span><span style="color: silver;"> </span>/<span style="color: silver;"> </span><span style="color: black; font-style: italic;">implicitHeight</span>)<span style="color: silver;"> </span>*<span style="color: silver;"> </span><span style="color: black; font-style: italic;">height</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">anchors.margins</span>:<span style="color: silver;"> </span>10</span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: maroon;">layer.enabled</span>:<span style="color: silver;"> </span>true</span></pre>
<br />
<pre><span style="font-family: Courier New, Courier, monospace;">}</span><!--EndFragment--></pre>
<br />
ThirtyBitImageItem's C++ declaration:<br />
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitImageItem</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">:</span><span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QQuickItem</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: navy;">Q_OBJECT</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">Q_PROPERTY</span><span style="color: black;">(</span><span style="color: purple;">Image</span><span style="color: black;">*</span><span style="color: silver;"> </span>image<span style="color: silver;"> </span>READ<span style="color: silver;"> </span>image<span style="color: silver;"> </span>WRITE<span style="color: silver;"> </span>setImage<span style="color: black;">)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">public</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">ThirtyBitImageItem</span><span style="color: black;">(</span><span style="color: purple;">QQuickItem</span><span style="color: black;">*</span><span style="color: silver;"> </span>parent<span style="color: black;">=</span><span style="color: olive;">nullptr</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">Image</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: silver;"> </span><span style="color: purple;">Image</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black;">image</span><span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: olive;">const</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">setImage</span><span style="color: black;">(</span><span style="color: purple;">Image</span><span style="color: black;">*</span><span style="color: silver;"> </span>image<span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">signals</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: olive;">slots</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: olive;">protected</span><span style="color: black;">:</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">Image</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: maroon;">m_image</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">std</span><span style="color: black;">::</span><span style="color: purple;">forward_list</span><span style="color: black;"><</span><span style="color: purple;">QMetaObject</span><span style="color: black;">::</span><span style="color: purple;">Connection</span><span style="color: black;">></span><span style="color: silver;"> </span><span style="color: maroon;">m_imageSignalConnections</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><b><span style="color: purple;">QSGNode</span><span style="color: black;">*</span><span style="color: silver;"> </span><span style="color: black; font-style: italic;">updatePaintNode</span><span style="color: black;">(</span><span style="color: purple;">QSGNode</span><span style="color: black;">*</span><span style="color: silver;"> </span>oldNode<span style="color: black;">,</span><span style="color: silver;"> </span><span style="color: purple;">UpdatePaintNodeData</span><span style="color: black;">*</span><span style="color: silver;"> </span>updatePaintNodeData<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: olive;">override</span><span style="color: black;">;</span></b></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: black;">onImageSizeChanged</span><span style="color: black;">(</span><span style="color: purple;">QSize</span><span style="color: silver;"> </span>size<span style="color: black;">);</span></span></pre>
<br />
<pre><span style="font-family: Courier New, Courier, monospace;">};</span><!--EndFragment--></pre>
<pre><!--EndFragment--></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><pre><!--EndFragment--></pre>
</pre>
</div>
<div>
<pre><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<span style="font-family: Courier New, Courier, monospace;">ThirtyBitImageItem</span> is to be our 30-bit capable version of the built-in QML type, <span style="font-family: Courier New, Courier, monospace;">Image</span> (implemented as <span style="font-family: Courier New, Courier, monospace;">QQuickImage</span> in C++). <span style="font-family: Courier New, Courier, monospace;">QQuickImage::updatePaintNode</span>'s implementation can be seen in <i>qt5/qtdeclarative/src/quick/items/qquickimage.cpp:</i></div>
<div>
<br />
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><!--StartFragment--><span style="font-family: Courier New, Courier, monospace;"><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*</span>QQuickImage<span style="color: black;">::</span>updatePaintNode<span style="color: black;">(</span><span style="color: purple;">QSGNode</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">oldNode</span><span style="color: black;">,</span><span style="color: silver;"> </span>UpdatePaintNodeData<span style="color: silver;"> </span><span style="color: black;">*)</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="color: black;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: navy;">Q_D</span><span style="color: black;">(</span>QQuickImage<span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: purple;">QSGTexture</span><span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">texture</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>sceneGraphRenderContext<span style="color: black;">()-></span>textureForFactory<span style="color: black;">(</span><span style="color: black;">d</span><span style="color: black;">-></span>pix<span style="color: black;">.</span>textureFactory<span style="color: black;">(),</span><span style="color: silver;"> </span>window<span style="color: black;">());</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Copy</span><span style="color: silver;"> </span><span style="color: green;">over</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">current</span><span style="color: silver;"> </span><span style="color: green;">texture</span><span style="color: silver;"> </span><span style="color: green;">state</span><span style="color: silver;"> </span><span style="color: green;">into</span><span style="color: silver;"> </span><span style="color: green;">the</span><span style="color: silver;"> </span><span style="color: green;">texture</span><span style="color: silver;"> </span><span style="color: green;">provider...</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(</span><span style="color: black;">d</span><span style="color: black;">-></span>provider<span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>provider<span style="color: black;">-></span>m_smooth<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>smooth<span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>provider<span style="color: black;">-></span>m_mipmap<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>mipmap<span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>provider<span style="color: black;">-></span>updateTexture<span style="color: black;">(</span><span style="color: black;">texture</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">texture</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span>width<span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;"><=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: silver;"> </span><span style="color: black;">||</span><span style="color: silver;"> </span>height<span style="color: black;">()</span><span style="color: silver;"> </span><span style="color: black;"><=</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: black;">oldNode</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span>QSGImageNode<span style="color: silver;"> </span><span style="color: black;">*</span><span style="color: black;">node</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">static_cast</span><span style="color: black;"><</span>QSGImageNode<span style="color: silver;"> </span><span style="color: black;">*>(</span><span style="color: black;">oldNode</span><span style="color: black;">);</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span><span style="color: black;">(!</span><span style="color: black;">node</span><span style="color: black;">)</span><span style="color: silver;"> </span><span style="color: black;">{</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>pixmapChanged<span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: olive;">true</span><span style="color: black;">;</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">node</span><span style="color: silver;"> </span><span style="color: black;">=</span><span style="color: silver;"> </span><span style="color: black;">d</span><span style="color: black;">-></span>sceneGraphContext<span style="color: black;">()-></span>createImageNode<span style="color: black;">();</span></span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: black;">}</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">...</span></span></pre>
<pre style="-qt-block-indent: 0; -qt-paragraph-type: empty; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;">
</span></pre>
<pre style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;"><span style="font-family: Courier New, Courier, monospace;"><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: black;">node</span><span style="color: black;">;</span></span></pre>
<br />
<pre><span style="font-family: Courier New, Courier, monospace;">}</span><!--EndFragment--></pre>
</div>
<div>
<pre></pre>
</div>
<pre><!--EndFragment--></pre>
<div>
<br /></div>
<div>
There's a lot going on, here. <span style="font-family: Courier New, Courier, monospace;">QQuickImage::updatePaintNode</span> is more complex than our first pass implementation needs to be, but it does provide some hints. Perhaps all we need is our own version of QSGImageNode that supports 30-bit color?</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-37811632789639509822015-12-02T13:13:00.002+01:002015-12-02T13:15:22.202+01:00Doing anything significant whatsoever with QML, part 2I implemented infrastructure for loading, manipulating, and displaying 16-bit-per-channel images in 30-bit color mode (IE, 10 bits for each R, G, and B component) with QML.<br />
<br />
And, on my Linux workstation with a Quadro K6000, running in 30-bit mode, it absolutely works. Banding in gradients is reduced to being just about imperceptible, even for stupidly evil cases such as filling my 3840x2160 display with a full range grayscale ramp. On the more practical end of things, microscopy images with subtle gradients finally look not-like-shit.<br />
<br />
<a href="https://github.com/erikhvatum/StackStream">Source code for this project is available as one of my many GitHub repos</a>.<br />
<br />
Stay tuned; when I'm not at the tail end of an 18-hour codeathon, and after I've added more GUI stuff, I'll post part 3 with all the details I really wish had been handed to me on a silver platter when I embarked on this, the QML experience.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-10207427262125173952015-11-24T22:31:00.001+01:002015-11-25T00:40:36.426+01:00Doing anything significant whatsoever with QML, part 1As a long time C++ and Python (PyQt) Qt developer, I have been observing the Qt project's move towards Javascript/ECMA script with a mixture of contempt and dismay. Since the early days of Qt4, every dot release of Qt included some new Javascript module or feature that would supposedly shift every paradigm. However, to be quite frank, the included examples for the latest Qt Javascript features were low quality hello-world type applications with glaring bugs. Nothing in the mosh pit of QtScript, QtDeclarative, QtQuick, and/or QML seemed appealing, and nobody anywhere seemed to be using it for anything.<br />
<br />
However, that is beginning to change. Wanting to fix some issues I encountered in KDE5/plasma, I discovered that it's largely QML. Even the start-menu/kicker thingy is QML. In order to make that menu taller, which was a simple click-drag operation in KDE4 (drag the top right corner to resize as if it were a window), KDE5 required me to edit a QML file. Needing to edit a file rather than simply click-dragging is moronic, but, in any case, I had manipulated my first QML file, and that QML file represents a GUI thing that I use quite often.<br />
<br />
My interest piqued, I spent an hour here and there over the course of the following weeks familiarizing myself with QML, Qt Quick2, the Qt Quick 2 scene graph, Javascript, interfacing C++ and QML, doing OpenGL in Javascript in QML, exposing QAbstractItemModel derivatives implemented in C++ to QML, and the like.<br />
<br />
My impression at this point:<br />
<br />
<ul>
<li>I like the ability to bind a Q_PROPERTY exposed by a C++ QObject derivative to fields in a user interface element declared in QML such that the GUI field updates when the property changes and the property is updated when the GUI field changes. Furthermore, it's awesome that simple expressions combining multiple such properties can be bound. There should be a way to do these things with Qt in C++ without connecting a billion signals and slots.</li>
<li>The anchor-based layout system is nice. There should be something like it in the Qt C++ API.</li>
<li>The provided Quick2 widgets are entirely worthless to me because their C++ implementations are all "private", so they can't be extended in useful way.</li>
<li>More generally, the C++ implementations of all of everything QML-related are "private", except for a few base classes, making all of everything QML-related entirely useless. Want to extend QML's integrated models? Not happening. Want to extend QML's anything what-so-fucking-ever? You can't.</li>
</ul>
<div>
In other words, as I write this, it's my opinion that QML and the entire Qt Javascript effort has been a complete waste of time whose only significant impact has been to cause the useful C++ parts of Qt to go essentially unmaintained for the last five years. For example, Qt 5.5.1 still doesn't support mouse event compression on X11, making it unsuitable for anything where mouse movement can cause computation that takes more than 1/60th of a second. Things so basic that they can't not work... don't work. And nobody cares, because javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript javascript.</div>
<div>
<br /></div>
<div>
Nonetheless, it is <i>conceivably possible</i> that I've had a rough time with QML simply because I'm thrashing about, ignorantly trying to do simple things in impossibly stupid ways that go against the flow. <i>Maybe</i> I would have a fine time if I just read the documentation, worked through a few tutorials, and gave up my hidebound C++-centric ways. So, I'm doing exactly that, and part 2 will detail my rebirth and first fresh steps with <strike>Jesus</strike> QML.</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-77428559460702475702015-06-16T20:22:00.000+02:002015-06-16T21:16:02.688+02:00Making IPython "?" magic show the correct doc string for custom descriptorsSuppose that in some directory in sys.path, there is a file, t.py:<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">class</span> Property:
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>, properties, name, default_value=<span style="color: blue;">None</span>, change_callback=<span style="color: blue;">None</span>, doc=<span style="color: blue;">None</span>):
<span style="color: purple;">self</span>.name = name
<span style="color: purple;">self</span>.var_name = <span style="color: teal;">'_'</span> + name
<span style="color: purple;">self</span>.default_value = default_value
<span style="color: purple;">self</span>.change_callback = change_callback
<span style="color: purple;">if</span> doc <span style="color: purple;">is</span> <span style="color: purple;">not</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.<span style="color: blue;">__doc__</span> = doc
properties.<span style="color: blue;">append</span>(<span style="color: purple;">self</span>)
<span style="color: purple;">def</span> <span style="color: #0000b0;">instantiate</span>(<span style="color: purple;">self</span>, obj_instance):
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name, <span style="color: purple;">self</span>.default_value)
<span style="color: purple;">def</span> <span style="color: #0000b0;">__get__</span>(<span style="color: purple;">self</span>, obj_instance, <span style="color: purple;">_</span>=<span style="color: blue;">None</span>):
<span style="color: purple;">if</span> obj_instance <span style="color: purple;">is</span> <span style="color: blue;">None</span>:
<span style="color: purple;">return</span> <span style="color: purple;">self</span>
<span style="color: purple;">return</span> <span style="color: blue;">getattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name)
<span style="color: purple;">def</span> <span style="color: #0000b0;">__set__</span>(<span style="color: purple;">self</span>, obj_instance, v):
<span style="color: purple;">if</span> v != <span style="color: blue;">getattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name):
<span style="color: purple;">if</span> <span style="color: purple;">self</span>.change_callback <span style="color: purple;">is</span> <span style="color: purple;">not</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.<span style="color: #0000b0;">change_callback</span>(obj_instance, v)
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name, v)
<span style="color: purple;">def</span> <span style="color: blue;">__delete__</span>(<span style="color: purple;">self</span>, obj_instance):
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.name, <span style="color: purple;">self</span>.default_value)
<span style="color: purple;">class</span> Foo:
properties = []
bar = <span style="color: #0000b0;">Property</span>(
properties,
<span style="color: teal;">'bar'</span>,
change_callback=<span style="color: purple;">lambda</span> <span style="color: purple;">_</span>, v: <span style="color: purple;">print</span>(<span style="color: teal;">"A Foo's bar changed to {}."</span>.<span style="color: #0000b0;">format</span>(v)),
doc=<span style="color: teal;">'The bar property of Foo: this is it. Its default value is None.\n'</span>
<span style="color: teal;">'Doing "del Foo_instance.bar" is equivalent to "Foo_instance.bar = None".'</span>)
bif = <span style="color: #0000b0;">Property</span>(
properties,
<span style="color: teal;">'bif'</span>,
<span style="color: #004e82;">42</span>,
doc=<span style="color: teal;">'bif property. "del Foo_instance.bif" reverts bif to its default value of 42.'</span>)
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>):
<span style="color: purple;">for</span> property <span style="color: purple;">in</span> <span style="color: purple;">self</span>.properties:
property.<span style="color: #0000b0;">instantiate</span>(<span style="color: purple;">self</span>)</pre>
</div>
<br />
t.py can then be used from IPython. For example:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">$ ipython<br />Python 3.4.3 (default, May 28 2015, 17:06:52) <br />Type "copyright", "credits" or "license" for more information.<br /><br />IPython 4.0.0-dev -- An enhanced Interactive Python.<br />? -> Introduction and overview of IPython's features.<br />%quickref -> Quick reference.<br />help -> Python's own help system.<br />object? -> Details about 'object', use 'object??' for extra details.<br /><br />In [1]: from t import Foo<br /><br />In [2]: f = Foo()<br /><br />In [3]: f.bar<br /><br />In [4]: f.bar?<br />Type: NoneType<br />String form: None<br />Docstring: <no docstring=""><br /><br />In [5]: f.bif<br />Out[5]: 42<br /><br />In [6]: f.bif?<br />Type: int<br />String form: 42<br />Docstring:<br />int(x=0) -> integer<br />int(x, base=10) -> integer<br /><br />Convert a number or string to an integer, or return 0 if no arguments<br />are given. If x is a number, return x.__int__(). For floating point<br />numbers, this truncates towards zero.<br /><br />If x is not a number or if base is given, then x must be a string,<br />bytes, or bytearray instance representing an integer literal in the<br />given base. The literal can be preceded by '+' or '-' and be surrounded<br />by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.<br />Base 0 means to interpret the base from the string as an integer literal.<br />>>> int('0b100', base=0)<br />4</no></span></span> <br />
<br />
IPython's "?" magic is not seeing our descriptor's doc strings. It does recognize doc strings for run-of-the-mill properties:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">In [1]: class C:<br /> ...: def get_baz(self):<br /> ...: return self.baz<br /> ...: baz = property(get_baz, doc='a baz property')<br /> ...: <br /><br />In [2]: c=C()<br /><br />In [3]: c.baz?<br />Type: property<br />String form: <property 0x7fc7e041bea8="" at="" object=""><br />Docstring: a baz property</property></span></span><br />
<br />
What's the difference? <a href="https://github.com/ipython/ipython/pull/4827/files">This is the difference</a>. IPython treats descriptors that are (or are derived from) "property" specially. What happens if we make our descriptor inherit from property, then? Let's try it: <br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">class</span> <span style="color: #0000b0;">Property</span>(<span style="font-size: large;"><b>property</b></span>):
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>, properties, name, default_value=<span style="color: blue;">None</span>, change_callback=<span style="color: blue;">None</span>, doc=<span style="color: blue;">None</span>):
<span style="color: purple;">self</span>.name = name
<span style="color: purple;">self</span>.var_name = <span style="color: teal;">'_'</span> + name
<span style="color: purple;">self</span>.default_value = default_value
<span style="color: purple;">self</span>.change_callback = change_callback
<span style="color: purple;">if</span> doc <span style="color: purple;">is</span> <span style="color: purple;">not</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.<span style="color: blue;">__doc__</span> = doc
properties.<span style="color: blue;">append</span>(<span style="color: purple;">self</span>)
<span style="color: purple;">def</span> <span style="color: #0000b0;">instantiate</span>(<span style="color: purple;">self</span>, obj_instance):
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name, <span style="color: purple;">self</span>.default_value)
<span style="color: purple;">def</span> <span style="color: #0000b0;">__get__</span>(<span style="color: purple;">self</span>, obj_instance, <span style="color: purple;">_</span>=<span style="color: blue;">None</span>):
<span style="color: purple;">if</span> obj_instance <span style="color: purple;">is</span> <span style="color: blue;">None</span>:
<span style="color: purple;">return</span> <span style="color: purple;">self</span>
<span style="color: purple;">return</span> <span style="color: blue;">getattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name)
<span style="color: purple;">def</span> <span style="color: #0000b0;">__set__</span>(<span style="color: purple;">self</span>, obj_instance, v):
<span style="color: purple;">if</span> v != <span style="color: blue;">getattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name):
<span style="color: purple;">if</span> <span style="color: purple;">self</span>.change_callback <span style="color: purple;">is</span> <span style="color: purple;">not</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.<span style="color: #0000b0;">change_callback</span>(obj_instance, v)
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.var_name, v)
<span style="color: purple;">def</span> <span style="color: blue;">__delete__</span>(<span style="color: purple;">self</span>, obj_instance):
<span style="color: blue;">setattr</span>(obj_instance, <span style="color: purple;">self</span>.name, <span style="color: purple;">self</span>.default_value)
<span style="color: purple;">class</span> Foo:
properties = []
bar = <span style="color: #0000b0;">Property</span>(
properties,
<span style="color: teal;">'bar'</span>,
change_callback=<span style="color: purple;">lambda</span> <span style="color: purple;">_</span>, v: <span style="color: purple;">print</span>(<span style="color: teal;">"A Foo's bar changed to {}."</span>.<span style="color: #0000b0;">format</span>(v)),
doc=<span style="color: teal;">'The bar property of Foo: this is it. Its default value is None.\n'</span>
<span style="color: teal;">'Doing "del Foo_instance.bar" is equivalent to "Foo_instance.bar = None".'</span>)
bif = <span style="color: #0000b0;">Property</span>(
properties,
<span style="color: teal;">'bif'</span>,
<span style="color: #004e82;">42</span>,
doc=<span style="color: teal;">'bif property. "del Foo_instance.bif" reverts bif to its default value of 42.'</span>)
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>):
<span style="color: purple;">for</span> property <span style="color: purple;">in</span> <span style="color: purple;">self</span>.properties:
property.<span style="color: #0000b0;">instantiate</span>(<span style="color: purple;">self</span>)
</pre>
</div>
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">$ ipython <br />Python 3.4.3 (default, May 28 2015, 17:06:52) <br />Type "copyright", "credits" or "license" for more information.<br /><br />IPython 4.0.0-dev -- An enhanced Interactive Python.<br />? -> Introduction and overview of IPython's features.<br />%quickref -> Quick reference.<br />help -> Python's own help system.<br />object? -> Details about 'object', use 'object??' for extra details.<br /><br />In [1]: from t import Foo<br /><br />In [2]: f = Foo()<br /><br />In [3]: f.bar<br /><br />In [4]: f.bar?<br />Type: Property<br />String form: <t .property="" 0x7fb1f781e7c8="" at="" object=""><br />File: ~/t.py<br />Docstring:<br />The bar property of Foo: this is it. Its default value is None.<br />Doing "del Foo_instance.bar" is equivalent to "Foo_instance.bar = None".<br /><br />In [5]: f.bif<br />Out[5]: 42<br /><br />In [6]: f.bif?<br />Type: Property<br />String form: <t .property="" 0x7fb1f781e888="" at="" object=""><br />File: ~/t.py<br />Docstring: bif property. "del Foo_instance.bif" reverts bif to its default value of 42.</t></t></span></span><br />
<br />
Our doc strings are seen, and things seem to work. If any reason exists why I should not derive my descriptors from property, I am not aware of it!Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-71140512564309987062015-06-04T20:15:00.002+02:002015-06-04T20:17:13.980+02:00xorg.conf for 60Hz 4k Dell UP3214Q with the NVidia Proprietary Driver<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: x-small;">It seems that Displayport 1.2 MST will never be properly supported on Linux, but it is possible to make it work perfectly with the some TwinView + Xinerama hackery. I use the following with a Quadro K6000 and UP3214Q:</span></span> </span></span><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Section "ServerLayout"<br /> Identifier "Layout0"<br /> Screen 0 "Screen0"<br /> Option "Xinerama" "1"<br />EndSection<br /><br />Section "Files"<br />EndSection<br /><br />Section "Monitor"<br /> Identifier "Monitor0"<br /> VendorName "Unknown"<br /> ModelName "Unknown"<br /> HorizSync 24.0 - 140.0<br /> VertRefresh 20.0 - 77.0<br /> Option "DPMS"<br /> Option "UseEDIDDpi" "FALSE"<br /> Option "DPI" "120x120"<br />EndSection<br /><br />Section "Device"<br /> Identifier "Device0"<br /> Driver "nvidia"<br /> VendorName "NVIDIA Corporation"<br />EndSection<br /><br />Section "Screen"<br /> Identifier "Screen0"<br /> Device "Device0"<br /> Monitor "Monitor0"<br /> DefaultDepth 24<br /> Option "metamodes" "DFP-4.9: 1920x2160 { ViewPortIn=1920x2160 }, DFP-4.8: 1920x2160 { ViewPortIn=1920x2160 }; DFP-4.9: 1920x2160 { ViewPortIn=1280x1440 }, DFP-4.8: 1920x2160 { ViewPortIn=1280x1440 }; DFP-4.9: 1920x2160 { ViewPortIn=960x1080 }, DFP-4.8: 1920x2160 { ViewPortIn=960x1080}; DFP-4.9: 1280x1440 { ViewPortIn=1280x1440 }, DFP-4.8: 1280x1440 { ViewPortIn=1280x1440 }; DFP-4.9: 960x1080 { ViewPortIn=960x1080 }, DFP-4.8: 960x1080 { ViewPortIn=960x1080}; DFP-4.9: 2560x1440 { ViewPortIn=2560x1440 }, NULL; DFP-4.9: 1920x1080 { ViewPortIn=1920x1080 }, NULL; DFP-4.9: 1920x1080_120 { ViewPortIn=1920x1080 }, NULL"<br /> Option "TwinView"<br /> Option "NoTwinViewXineramaInfo" "1"<br /> Option "TwinViewXineramaInfoOverride" "3840x2160+0+0"<br /> Option "ConnectedMonitor" "DFP-4.9, DFP-4.8"<br /> Option "TwinViewOrientation" "LeftOf"<br /> SubSection "Display"<br /> Depth 24<br /> EndSubSection<br />EndSection</span></span>Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-39942658350450228762015-04-14T20:16:00.001+02:002015-04-14T20:16:04.714+02:00Cython Compiler, Called by Distutils!!! YEAH, YOU, CYTHON! I HAVE AN OPTION FOR YOU!<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">[12:58 PM][ehvatum@pincuslab-2:~/zplrepo/ris_widget]> python3 setup.py build_ext --inplace<br />running build_ext<br />skipping 'cython/_ndimage_statistics.cpp' Cython extension (up-to-date)</span></span><br />
<br />
Suppose that since Cython last built that .cpp file, I modified <i>Cython iteself</i>, and it would now generate significantly different output. In that case, I want to regenerate the .cpp.<br />
<br />
So, how about we <b>not</b> skip rebuilding the .cpp file? What about that? I want to not skip it.<br />
<br />
<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">[12:58 PM][ehvatum@pincuslab-2:~/zplrepo/ris_widget]> cython --help<br />Cython (http://cython.org) is a compiler for code written in the<br />Cython language. Cython is based on Pyrex by Greg Ewing.<br /><br />Usage: cython [options] sourcefile.{pyx,py} ...<br /><br />Options:<br /> -V, --version Display version number of cython compiler<br /> -l, --create-listing Write error messages to a listing file<br /> -I, --include-dir <directory> Search for include files in named directory<br /> (multiple include directories are allowed).<br /> -o, --output-file <filename> Specify name of generated C file<br /> -t, --timestamps Only compile newer source files<br /> <span style="font-size: small;"><b>-f, --force Compile all source files (overrides implied -t)</b></span><br /> -v, --verbose Be verbose, print file names on multiple compilation<br /> -p, --embed-positions If specified, the positions in Cython files of each<br /> function definition is embedded in its docstring.<br /> --cleanup <level> Release interned objects on python exit, for memory debugging.<br /> Level indicates aggressiveness, default 0 releases nothing.<br /> -w, --working <directory> Sets the working directory for Cython (the directory modules<br /> are searched from)<br /> --gdb Output debug information for cygdb<br /> --gdb-outdir <directory> Specify gdb debug information output directory. Implies --gdb.<br /><br /> -D, --no-docstrings Strip docstrings from the compiled module.<br /> -a, --annotate Produce a colorized HTML version of the source.<br /> --line-directives Produce #line directives pointing to the .pyx source<br /> --cplus Output a C++ rather than C file.<br /> --embed[=<method_name>] Generate a main() function that embeds the Python interpreter.<br /> -2 Compile based on Python-2 syntax and code semantics.<br /> -3 Compile based on Python-3 syntax and code semantics.<br /> --lenient Change some compile time errors to runtime errors to<br /> improve Python compatibility<br /> --capi-reexport-cincludes Add cincluded headers to any auto-generated header files.<br /> --fast-fail Abort the compilation on the first error<br /> --warning-errors, -Werror Make all warnings into errors<br /> --warning-extra, -Wextra Enable extra warnings<br /> -X, --directive <name>=<value>[,<name a="" compiler="" directive="" overrides="" span="" value=""></name></value></name></method_name></directory></directory></level></filename></directory></span></span><br />
<br />
That sounds good. We want to feed this "-f" option to the cython invocation distutils makes on our behalf. Our setup.py file is the logic place to do this, as it kicks off the whole distutils <strike>horror show</strike> build process. Let's look at our setup.py file:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>core</span><span> </span><span style="color: purple;">import</span><span> </span><span>setup</span>
<span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<span style="color: purple;">import</span><span> </span><span>numpy</span>
<span style="color: purple;">import</span><span> </span><span>os</span>
<span style="color: purple;">import</span><span> </span><span>subprocess</span>
<span style="color: purple;">import</span><span> </span><span style="color: blue;">sys</span>
<span>cpp_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics_impl.cpp'</span>
<span>cython_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.pyx'</span>
<span>cythoned_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.cpp'</span>
<span>cython_source_deps</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: teal;">'cython/_ndimage_statistics_impl.h'</span><span>]</span>
<span>include_dirs</span><span> </span><span>=</span><span> </span><span>[</span><span>numpy</span><span>.</span><span style="color: #0000b0;">get_include</span><span>()]</span>
<span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>extra_link_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>define_macros</span><span> </span><span>=</span><span> </span><span>[]</span>
<span style="color: purple;">if</span><span> </span><span style="color: blue;">sys</span><span>.</span><span>platform</span><span> </span><span>!=</span><span> </span><span style="color: teal;">'win32'</span><span>:</span>
<span> </span><span>extra_compile_args</span><span>.</span><span style="color: #0000b0;">extend</span><span>((</span><span style="color: teal;">'-O3'</span><span>,</span><span> </span><span style="color: teal;">'-march=native'</span><span>))</span>
<span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span> </span><span style="color: purple;">import</span><span> </span><span>build_ext</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cython_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>cmdclass</span><span> </span><span>=</span><span> </span><span>{</span><span style="color: teal;">'build_ext'</span><span> </span><span>:</span><span> </span><span>build_ext</span><span>},</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span>
<span style="color: purple;">except</span><span> </span><span style="color: blue;">ImportError</span><span>:</span>
<span> </span><span style="color: purple;">print</span><span>(</span><span style="color: teal;">'Cython does not appear to be installed. Attempting to use pre-made cpp file...'</span><span>)</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cythoned_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span></pre>
</div>
<br />
Alright... I guess we can look at distutils.extension.Extension to see if it will accept some kind of cython compiler parameter option.<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">class</span><span> </span><span>Extension</span><span>:</span>
<span> </span><span style="color: teal;">"""Just a collection of attributes that describes an extension</span>
<span style="color: teal;"> module and everything needed to build it (hopefully in a portable</span>
<span style="color: teal;"> way, but there are hooks that let you be as unportable as you need).</span>
<span style="color: teal;"> Instance attributes:</span>
<span style="color: teal;"> name : string</span>
<span style="color: teal;"> the full name of the extension, including any packages -- ie.</span>
<span style="color: teal;"> *not* a filename or pathname, but Python dotted name</span>
<span style="color: teal;"> sources : [string]</span>
<span style="color: teal;"> list of source filenames, relative to the distribution root</span>
<span style="color: teal;"> (where the setup script lives), in Unix form (slash-separated)</span>
<span style="color: teal;"> for portability. Source files may be C, C++, SWIG (.i),</span>
<span style="color: teal;"> platform-specific resource files, or whatever else is recognized</span>
<span style="color: teal;"> by the "build_ext" command as source for a Python extension.</span>
<span style="color: teal;"> include_dirs : [string]</span>
<span style="color: teal;"> list of directories to search for C/C++ header files (in Unix</span>
<span style="color: teal;"> form for portability)</span>
<span style="color: teal;"> define_macros : [(name : string, value : string|None)]</span>
<span style="color: teal;"> list of macros to define; each macro is defined using a 2-tuple,</span>
<span style="color: teal;"> where 'value' is either the string to define it to or None to</span>
<span style="color: teal;"> define it without a particular value (equivalent of "#define</span>
<span style="color: teal;"> FOO" in source or -DFOO on Unix C compiler command line)</span>
<span style="color: teal;"> undef_macros : [string]</span>
<span style="color: teal;"> list of macros to undefine explicitly</span>
<span style="color: teal;"> library_dirs : [string]</span>
<span style="color: teal;"> list of directories to search for C/C++ libraries at link time</span>
<span style="color: teal;"> libraries : [string]</span>
<span style="color: teal;"> list of library names (not filenames or paths) to link against</span>
<span style="color: teal;"> runtime_library_dirs : [string]</span>
<span style="color: teal;"> list of directories to search for C/C++ libraries at run time</span>
<span style="color: teal;"> (for shared extensions, this is when the extension is loaded)</span>
<span style="color: teal;"> extra_objects : [string]</span>
<span style="color: teal;"> list of extra files to link with (eg. object files not implied</span>
<span style="color: teal;"> by 'sources', static library that must be explicitly specified,</span>
<span style="color: teal;"> binary resource files, etc.)</span>
<span style="color: teal;"> extra_compile_args : [string]</span>
<span style="color: teal;"> any extra platform- and compiler-specific information to use</span>
<span style="color: teal;"> when compiling the source files in 'sources'. For platforms and</span>
<span style="color: teal;"> compilers where "command line" makes sense, this is typically a</span>
<span style="color: teal;"> list of command-line arguments, but for other platforms it could</span>
<span style="color: teal;"> be anything.</span>
<span style="color: teal;"> extra_link_args : [string]</span>
<span style="color: teal;"> any extra platform- and compiler-specific information to use</span>
<span style="color: teal;"> when linking object files together to create the extension (or</span>
<span style="color: teal;"> to create a new static Python interpreter). Similar</span>
<span style="color: teal;"> interpretation as for 'extra_compile_args'.</span>
<span style="color: teal;"> export_symbols : [string]</span>
<span style="color: teal;"> list of symbols to be exported from a shared extension. Not</span>
<span style="color: teal;"> used on all platforms, and not generally necessary for Python</span>
<span style="color: teal;"> extensions, which typically export exactly one symbol: "init" +</span>
<span style="color: teal;"> extension_name.</span>
<span style="color: teal;"> swig_opts : [string]</span>
<span style="color: teal;"> any extra options to pass to SWIG if a source file has the .i</span>
<span style="color: teal;"> extension.</span>
<span style="color: teal;"> depends : [string]</span>
<span style="color: teal;"> list of files that the extension depends on</span>
<span style="color: teal;"> language : string</span>
<span style="color: teal;"> extension language (i.e. "c", "c++", "objc"). Will be detected</span>
<span style="color: teal;"> from the source extensions if not provided.</span>
<span style="color: teal;"> optional : boolean</span>
<span style="color: teal;"> specifies that a build failure in the extension should not abort the</span>
<span style="color: teal;"> build process, but simply not install the failing extension.</span>
<span style="color: teal;"> """</span>
<span> </span><span style="color: green;"># When adding arguments to this constructor, be sure to update</span>
<span> </span><span style="color: green;"># setup_keywords in core.py.</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: blue;">__init__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>sources</span><span>,</span>
<span> </span><span>include_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>define_macros</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>undef_macros</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>library_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>libraries</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>runtime_library_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_objects</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_compile_args</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_link_args</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>export_symbols</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>swig_opts</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>depends</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>language</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>optional</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>**</span><span>kw</span><span> </span><span style="color: green;"># To catch unknown keywords</span>
<span> </span><span>):</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span style="color: #0000b0;">isinstance</span><span>(</span><span>name</span><span>,</span><span> </span><span style="color: blue;">str</span><span>):</span>
<span> </span><span style="color: purple;">raise</span><span> </span><span style="color: #0000b0;">AssertionError</span><span>(</span><span style="color: teal;">"'name' must be a string"</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>(</span><span style="color: #0000b0;">isinstance</span><span>(</span><span>sources</span><span>,</span><span> </span><span>list</span><span>)</span><span> </span><span style="color: purple;">and</span>
<span> </span><span style="color: #0000b0;">all</span><span>(</span><span style="color: #0000b0;">isinstance</span><span>(</span><span>v</span><span>,</span><span> </span><span style="color: blue;">str</span><span>)</span><span> </span><span style="color: purple;">for</span><span> </span><span>v</span><span> </span><span style="color: purple;">in</span><span> </span><span>sources</span><span>)):</span>
<span> </span><span style="color: purple;">raise</span><span> </span><span style="color: #0000b0;">AssertionError</span><span>(</span><span style="color: teal;">"'sources' must be a list of strings"</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>name</span><span> </span><span>=</span><span> </span><span>name</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>sources</span><span> </span><span>=</span><span> </span><span>sources</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>undef_macros</span><span> </span><span>=</span><span> </span><span>undef_macros</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>library_dirs</span><span> </span><span>=</span><span> </span><span>library_dirs</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>libraries</span><span> </span><span>=</span><span> </span><span>libraries</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>runtime_library_dirs</span><span> </span><span>=</span><span> </span><span>runtime_library_dirs</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>extra_objects</span><span> </span><span>=</span><span> </span><span>extra_objects</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>export_symbols</span><span> </span><span>=</span><span> </span><span>export_symbols</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>swig_opts</span><span> </span><span>=</span><span> </span><span>swig_opts</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>depends</span><span> </span><span>=</span><span> </span><span>depends</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>language</span><span> </span><span>=</span><span> </span><span>language</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>optional</span><span> </span><span>=</span><span> </span><span>optional</span>
<span> </span><span style="color: green;"># If there are unknown keyword options, warn about them</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: blue;">len</span><span>(</span><span>kw</span><span>)</span><span> </span><span>></span><span> </span><span style="color: #004e82;">0</span><span>:</span>
<span> </span><span>options</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: blue;">repr</span><span>(</span><span>option</span><span>)</span><span> </span><span style="color: purple;">for</span><span> </span><span>option</span><span> </span><span style="color: purple;">in</span><span> </span><span>kw</span><span>]</span>
<span> </span><span>options</span><span> </span><span>=</span><span> </span><span style="color: teal;">', '</span><span>.</span><span style="color: #0000b0;">join</span><span>(</span><span style="color: #0000b0;">sorted</span><span>(</span><span>options</span><span>))</span>
<span> </span><span>msg</span><span> </span><span>=</span><span> </span><span style="color: teal;">"Unknown Extension options: %s"</span><span> </span><span>%</span><span> </span><span>options</span>
<span> </span><span>warnings</span><span>.</span><span style="color: #0000b0;">warn</span><span>(</span><span>msg</span><span>)</span></pre>
</div>
<br />
Unsurprisingly, distutils.extension.Extension.__init__(...) not only doesn't accept any cython-specific options - it also yells about any you might attempt to supply. I'm an intelligent person, but the docs just don't seem to be helping. So, I fire up my debugger and wade into our distutils.core.setup(..) call.<br />
<br />In short order, I find myself stepping into the Cython.Distutils.build_ext.build_ext.cython_sources(..) member function. Part of that function:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span> </span><span style="color: green;"># Setup create_list and cplus from the extension options if</span>
<span> </span><span style="color: green;"># <b><span style="font-size: large;">Cython.Distutils.extension.Extension is used</span></b>, otherwise just</span>
<span> </span><span style="color: green;"># use what was parsed from the command-line or the configuration file.</span>
<span> </span><span style="color: green;"># cplus will also be set to true is extension.language is equal to</span>
<span> </span><span style="color: green;"># 'C++' or 'c++'.</span>
<span> </span><span style="color: green;">#try:</span>
<span> </span><span style="color: green;"># create_listing = self.cython_create_listing or \</span>
<span> </span><span style="color: green;"># extension.cython_create_listing</span>
<span> </span><span style="color: green;"># cplus = self.cython_cplus or \</span>
<span> </span><span style="color: green;"># extension.cython_cplus or \</span>
<span> </span><span style="color: green;"># (extension.language != None and \</span>
<span> </span><span style="color: green;"># extension.language.lower() == 'c++')</span>
<span> </span><span style="color: green;">#except AttributeError:</span>
<span> </span><span style="color: green;"># create_listing = self.cython_create_listing</span>
<span> </span><span style="color: green;"># cplus = self.cython_cplus or \</span>
<span> </span><span style="color: green;"># (extension.language != None and \</span>
<span> </span><span style="color: green;"># extension.language.lower() == 'c++')</span>
<span> </span><span>create_listing</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_create_listing</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_create_listing'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>line_directives</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_line_directives</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_line_directives'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>no_c_in_traceback</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>no_c_in_traceback</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'no_c_in_traceback'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>cplus</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_cplus</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_cplus'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span>(</span><span>extension</span><span>.</span><span>language</span><span> </span><span style="color: purple;">and</span><span> </span><span>extension</span><span>.</span><span>language</span><span>.</span><span style="color: #0000b0;">lower</span><span>()</span><span> </span><span>==</span><span> </span><span style="color: teal;">'c++'</span><span>)</span>
<span> </span><span>cython_gen_pxi</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gen_pxi</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_gen_pxi'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>cython_gdb</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gdb</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_gdb'</span><span>,</span><span> </span><span style="color: blue;">False</span><span>)</span>
<span> </span><span>cython_compile_time_env</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_compile_time_env</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_compile_time_env'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>)</span>
<span> </span><span style="color: green;"># Set up the include_path for the Cython compiler:</span>
<span> </span><span style="color: green;"># 1. Start with the command line option.</span>
<span> </span><span style="color: green;"># 2. Add in any (unique) paths from the extension</span>
<span> </span><span style="color: green;"># cython_include_dirs (if Cython.Distutils.extension is used).</span>
<span> </span><span style="color: green;"># 3. Add in any (unique) paths from the extension include_dirs</span>
<span> </span><span>includes</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span>
<span> </span><span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>extension</span><span>.</span><span>cython_include_dirs</span><span>:</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>includes</span><span>:</span>
<span> </span><span>includes</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>i</span><span>)</span>
<span> </span><span style="color: purple;">except</span><span> </span><span style="color: blue;">AttributeError</span><span>:</span>
<span> </span><span style="color: purple;">pass</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>extension</span><span>.</span><span>include_dirs</span><span>:</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>includes</span><span>:</span>
<span> </span><span>includes</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>i</span><span>)</span>
<span> </span><span style="color: green;"># Set up Cython compiler directives:</span>
<span> </span><span style="color: green;"># 1. Start with the command line option.</span>
<span> </span><span style="color: green;"># 2. Add in any (unique) entries from the extension</span>
<span> </span><span style="color: green;"># cython_directives (if Cython.Distutils.extension is used).</span>
<span> </span><span>directives</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: blue;">hasattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">"cython_directives"</span><span>):</span>
<span> </span><span>directives</span><span>.</span><span style="color: #0000b0;">update</span><span>(</span><span>extension</span><span>.</span><span>cython_directives</span><span>)</span></pre>
</div>
</div>
<br />
Sounds promising. Let's take a look at Cython.Distutils.extension.Extension:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">class</span><span> </span><span style="color: #0000b0;">Extension</span><span>(</span><span>_Extension</span><span>.</span><span>Extension</span><span>):</span>
<span> </span><span style="color: green;"># When adding arguments to this constructor, be sure to update</span>
<span> </span><span style="color: green;"># user_options.extend in build_ext.py.</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: blue;">__init__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>sources</span><span>,</span>
<span> </span><span>include_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>define_macros</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>undef_macros</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>library_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>libraries</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>runtime_library_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_objects</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_compile_args</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>extra_link_args</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>export_symbols</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: green;">#swig_opts=None,</span>
<span> </span><span>depends</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>language</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>cython_include_dirs</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>cython_directives</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>cython_create_listing</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_line_directives</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_cplus</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_c_in_temp</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_gen_pxi</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_gdb</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>no_c_in_traceback</span><span>=</span><span style="color: blue;">False</span><span>,</span>
<span> </span><span>cython_compile_time_env</span><span>=</span><span style="color: blue;">None</span><span>,</span>
<span> </span><span>**</span><span>kw</span><span>):</span>
<span> </span><span style="color: green;"># Translate pyrex_X to cython_X for backwards compatibility.</span>
<span> </span><span>had_pyrex_options</span><span> </span><span>=</span><span> </span><span style="color: blue;">False</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>key</span><span> </span><span style="color: purple;">in</span><span> </span><span style="color: #0000b0;">list</span><span>(</span><span>kw</span><span>.</span><span style="color: #0000b0;">keys</span><span>()):</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>key</span><span>.</span><span style="color: #0000b0;">startswith</span><span>(</span><span style="color: teal;">'pyrex_'</span><span>):</span>
<span> </span><span>had_pyrex_options</span><span> </span><span>=</span><span> </span><span style="color: blue;">True</span>
<span> </span><span>kw</span><span>[</span><span style="color: teal;">'cython'</span><span> </span><span>+</span><span> </span><span>key</span><span>[</span><span style="color: #004e82;">5</span><span>:]]</span><span> </span><span>=</span><span> </span><span>kw</span><span>.</span><span style="color: #0000b0;">pop</span><span>(</span><span>key</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>had_pyrex_options</span><span>:</span>
<span> </span><span>Extension</span><span>.</span><span style="color: blue;">__init__</span><span>(</span>
<span> </span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>sources</span><span>,</span>
<span> </span><span>include_dirs</span><span>=</span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span>=</span><span>define_macros</span><span>,</span>
<span> </span><span>undef_macros</span><span>=</span><span>undef_macros</span><span>,</span>
<span> </span><span>library_dirs</span><span>=</span><span>library_dirs</span><span>,</span>
<span> </span><span>libraries</span><span>=</span><span>libraries</span><span>,</span>
<span> </span><span>runtime_library_dirs</span><span>=</span><span>runtime_library_dirs</span><span>,</span>
<span> </span><span>extra_objects</span><span>=</span><span>extra_objects</span><span>,</span>
<span> </span><span>extra_compile_args</span><span>=</span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span>=</span><span>extra_link_args</span><span>,</span>
<span> </span><span>export_symbols</span><span>=</span><span>export_symbols</span><span>,</span>
<span> </span><span style="color: green;">#swig_opts=swig_opts,</span>
<span> </span><span>depends</span><span>=</span><span>depends</span><span>,</span>
<span> </span><span>language</span><span>=</span><span>language</span><span>,</span>
<span> </span><span>no_c_in_traceback</span><span>=</span><span>no_c_in_traceback</span><span>,</span>
<span> </span><span>**</span><span>kw</span><span>)</span>
<span> </span><span style="color: purple;">return</span>
<span> </span><span>_Extension</span><span>.</span><span>Extension</span><span>.</span><span style="color: blue;">__init__</span><span>(</span>
<span> </span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>sources</span><span>,</span>
<span> </span><span>include_dirs</span><span>=</span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span>=</span><span>define_macros</span><span>,</span>
<span> </span><span>undef_macros</span><span>=</span><span>undef_macros</span><span>,</span>
<span> </span><span>library_dirs</span><span>=</span><span>library_dirs</span><span>,</span>
<span> </span><span>libraries</span><span>=</span><span>libraries</span><span>,</span>
<span> </span><span>runtime_library_dirs</span><span>=</span><span>runtime_library_dirs</span><span>,</span>
<span> </span><span>extra_objects</span><span>=</span><span>extra_objects</span><span>,</span>
<span> </span><span>extra_compile_args</span><span>=</span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span>=</span><span>extra_link_args</span><span>,</span>
<span> </span><span>export_symbols</span><span>=</span><span>export_symbols</span><span>,</span>
<span> </span><span style="color: green;">#swig_opts=swig_opts,</span>
<span> </span><span>depends</span><span>=</span><span>depends</span><span>,</span>
<span> </span><span>language</span><span>=</span><span>language</span><span>,</span>
<span> </span><span>**</span><span>kw</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span> </span><span>=</span><span> </span><span>cython_include_dirs</span><span> </span><span style="color: purple;">or</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span><span> </span><span>=</span><span> </span><span>cython_directives</span><span> </span><span style="color: purple;">or</span><span> </span><span>{}</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_create_listing</span><span> </span><span>=</span><span> </span><span>cython_create_listing</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_line_directives</span><span> </span><span>=</span><span> </span><span>cython_line_directives</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_cplus</span><span> </span><span>=</span><span> </span><span>cython_cplus</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_c_in_temp</span><span> </span><span>=</span><span> </span><span>cython_c_in_temp</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gen_pxi</span><span> </span><span>=</span><span> </span><span>cython_gen_pxi</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gdb</span><span> </span><span>=</span><span> </span><span>cython_gdb</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>no_c_in_traceback</span><span> </span><span>=</span><span> </span><span>no_c_in_traceback</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_compile_time_env</span><span> </span><span>=</span><span> </span><span>cython_compile_time_env</span></pre>
</div>
<br />
I don't see anything about our force option, but perhaps it will can be a cython_directives entry or even a kw dict entry. Alright, let's replace our distutils Extension object with a Cython.Distutils Extension object supplied with a cython_directives dict containing force = True:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>core</span><span> </span><span style="color: purple;">import</span><span> </span><span>setup</span>
<span style="color: purple;">import</span><span> </span><span>numpy</span>
<span style="color: purple;">import</span><span> </span><span>os</span>
<span style="color: purple;">import</span><span> </span><span>subprocess</span>
<span style="color: purple;">import</span><span> </span><span style="color: blue;">sys</span>
<span>cpp_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics_impl.cpp'</span>
<span>cython_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.pyx'</span>
<span>cythoned_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.cpp'</span>
<span>cython_source_deps</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: teal;">'cython/_ndimage_statistics_impl.h'</span><span>]</span>
<span>include_dirs</span><span> </span><span>=</span><span> </span><span>[</span><span>numpy</span><span>.</span><span style="color: #0000b0;">get_include</span><span>()]</span>
<span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>extra_link_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>define_macros</span><span> </span><span>=</span><span> </span><span>[]</span>
<span style="color: purple;">if</span><span> </span><span style="color: blue;">sys</span><span>.</span><span>platform</span><span> </span><span>!=</span><span> </span><span style="color: teal;">'win32'</span><span>:</span>
<span> </span><span>extra_compile_args</span><span>.</span><span style="color: #0000b0;">extend</span><span>((</span><span style="color: teal;">'-O3'</span><span>,</span><span> </span><span style="color: teal;">'-march=native'</span><span>))</span>
<span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span> </span><span style="color: purple;">import</span><span> </span><span>build_ext</span>
<span> </span><span>build_ext</span><span>.</span><span>force</span><span> </span><span>=</span><span> </span><span style="color: blue;">True</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cython_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span><span>,</span>
<span> </span><span>cython_directives</span><span>={</span>
<span> </span><span style="color: teal;">'language_level'</span><span> </span><span>:</span><span> </span><span style="color: #004e82;">3</span><span>,</span>
<span> </span><span style="color: teal;">'force'</span><span> </span><span>:</span><span> </span><span style="color: blue;">True</span>
<span> </span><span>}</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>cmdclass</span><span> </span><span>=</span><span> </span><span>{</span><span style="color: teal;">'build_ext'</span><span> </span><span>:</span><span> </span><span>build_ext</span><span>},</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span>
<span style="color: purple;">except</span><span> </span><span style="color: blue;">ImportError</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<span> </span><span style="color: purple;">print</span><span>(</span><span style="color: teal;">'Cython does not appear to be installed. Attempting to use pre-made cpp file...'</span><span>,</span><span> </span><span>file</span><span>=</span><span style="color: blue;">sys</span><span>.</span><span style="color: blue;">stderr</span><span>)</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cythoned_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span></pre>
</div>
<br />
Did this fix it?<br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">[06:09 PM][ehvatum@pincuslab-scope:~/zplrepo/ris_widget]> python setup.py build_ext --inplace<br />running build_ext<br />skipping 'cython/_ndimage_statistics.cpp' Cython extension (up-to-date)</span></span><br />
<br />
Nope. How about supplying force as a kw entry:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>core</span><span> </span><span style="color: purple;">import</span><span> </span><span>setup</span>
<span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<span style="color: purple;">import</span><span> </span><span>numpy</span>
<span style="color: purple;">import</span><span> </span><span>os</span>
<span style="color: purple;">import</span><span> </span><span>subprocess</span>
<span style="color: purple;">import</span><span> </span><span style="color: blue;">sys</span>
<span>cpp_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics_impl.cpp'</span>
<span>cython_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.pyx'</span>
<span>cythoned_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.cpp'</span>
<span>cython_source_deps</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: teal;">'cython/_ndimage_statistics_impl.h'</span><span>]</span>
<span>include_dirs</span><span> </span><span>=</span><span> </span><span>[</span><span>numpy</span><span>.</span><span style="color: #0000b0;">get_include</span><span>()]</span>
<span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>extra_link_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>define_macros</span><span> </span><span>=</span><span> </span><span>[]</span>
<span style="color: purple;">if</span><span> </span><span style="color: blue;">sys</span><span>.</span><span>platform</span><span> </span><span>!=</span><span> </span><span style="color: teal;">'win32'</span><span>:</span>
<span> </span><span>extra_compile_args</span><span>.</span><span style="color: #0000b0;">extend</span><span>((</span><span style="color: teal;">'-O3'</span><span>,</span><span> </span><span style="color: teal;">'-march=native'</span><span>))</span>
<span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span> </span><span style="color: purple;">import</span><span> </span><span>build_ext</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cython_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span><span>,</span>
<span> </span><span>cython_directives</span><span>={</span><span style="color: teal;">'language_level'</span><span> </span><span>:</span><span> </span><span style="color: #004e82;">3</span><span>},</span>
<span> </span><span>force</span><span>=</span><span style="color: blue;">True</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>cmdclass</span><span> </span><span>=</span><span> </span><span>{</span><span style="color: teal;">'build_ext'</span><span> </span><span>:</span><span> </span><span>build_ext</span><span>},</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span>
<span style="color: purple;">except</span><span> </span><span style="color: blue;">ImportError</span><span>:</span>
<span> </span><span style="color: purple;">print</span><span>(</span><span style="color: teal;">'Cython does not appear to be installed. Attempting to use pre-made cpp file...'</span><span>)</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cythoned_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span></pre>
</div>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><br /></span></span>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">[10:41 AM][ehvatum@pincuslab-scope:~/zplrepo/ris_widget]> python setup.py build_ext --inplace<br />/usr/lib64/python3.4/distutils/extension.py:132: UserWarning: Unknown Extension options: 'cython_directives', 'force'<br /> warnings.warn(msg)<br />running build_ext<br />skipping 'cython/_ndimage_statistics.cpp' Cython extension (up-to-date)</span></span><br />
<br />
Nope.<br />
<br />
In fact, no variation of the above will ever work. Why not? Let's look at Cython.Distutils.build_ext.build_ext:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">class</span><span> </span><span style="color: #0000b0;">build_ext</span><span>(</span><span>_build_ext</span><span>.</span><span>build_ext</span><span>):</span>
<span> </span><span>description</span><span> </span><span>=</span><span> </span><span style="color: teal;">"build C/C++ and Cython extensions (compile/link to build directory)"</span>
<span> </span><span>sep_by</span><span> </span><span>=</span><span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span>sep_by</span>
<span> </span><span>user_options</span><span> </span><span>=</span><span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span>user_options</span>
<span> </span><span>boolean_options</span><span> </span><span>=</span><span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span>boolean_options</span>
<span> </span><span>help_options</span><span> </span><span>=</span><span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span>help_options</span>
<span> </span><span style="color: green;"># Add the pyrex specific data.</span>
<span> </span><span>user_options</span><span>.</span><span style="color: #0000b0;">extend</span><span>([</span>
<span> </span><span>(</span><span style="color: teal;">'cython-cplus'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate C++ source files"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-create-listing'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"write errors to a listing file"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-line-directives'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"emit source line directives"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-include-dirs='</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"path to the Cython include files"</span><span> </span><span>+</span><span> </span><span>sep_by</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-c-in-temp'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"put generated C files in temp directory"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-gen-pxi'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate .pxi file for public declarations"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-directives='</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"compiler directive overrides"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-gdb'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate debug information for cygdb"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'cython-compile-time-env'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"cython compile time environment"</span><span>),</span>
<span> </span>
<span> </span><span style="color: green;"># For backwards compatibility.</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-cplus'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate C++ source files"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-create-listing'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"write errors to a listing file"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-line-directives'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"emit source line directives"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-include-dirs='</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"path to the Cython include files"</span><span> </span><span>+</span><span> </span><span>sep_by</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-c-in-temp'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"put generated C files in temp directory"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-gen-pxi'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate .pxi file for public declarations"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-directives='</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"compiler directive overrides"</span><span>),</span>
<span> </span><span>(</span><span style="color: teal;">'pyrex-gdb'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>,</span>
<span> </span><span style="color: teal;">"generate debug information for cygdb"</span><span>),</span>
<span> </span><span>])</span>
<span> </span><span>boolean_options</span><span>.</span><span style="color: #0000b0;">extend</span><span>([</span>
<span> </span><span style="color: teal;">'cython-cplus'</span><span>,</span><span> </span><span style="color: teal;">'cython-create-listing'</span><span>,</span><span> </span><span style="color: teal;">'cython-line-directives'</span><span>,</span>
<span> </span><span style="color: teal;">'cython-c-in-temp'</span><span>,</span><span> </span><span style="color: teal;">'cython-gdb'</span><span>,</span>
<span> </span>
<span> </span><span style="color: green;"># For backwards compatibility.</span>
<span> </span><span style="color: teal;">'pyrex-cplus'</span><span>,</span><span> </span><span style="color: teal;">'pyrex-create-listing'</span><span>,</span><span> </span><span style="color: teal;">'pyrex-line-directives'</span><span>,</span>
<span> </span><span style="color: teal;">'pyrex-c-in-temp'</span><span>,</span><span> </span><span style="color: teal;">'pyrex-gdb'</span><span>,</span>
<span> </span><span>])</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: #0000b0;">initialize_options</span><span>(</span><span style="color: purple;">self</span><span>):</span>
<span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span style="color: #0000b0;">initialize_options</span><span>(</span><span style="color: purple;">self</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_cplus</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_create_listing</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_line_directives</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_c_in_temp</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gen_pxi</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gdb</span><span> </span><span>=</span><span> </span><span style="color: blue;">False</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>no_c_in_traceback</span><span> </span><span>=</span><span> </span><span style="color: #004e82;">0</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_compile_time_env</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span>
<span> </span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: blue;">__getattr__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>):</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>name</span><span>[:</span><span style="color: #004e82;">6</span><span>]</span><span> </span><span>==</span><span> </span><span style="color: teal;">'pyrex_'</span><span>:</span>
<span> </span><span style="color: purple;">return</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span style="color: teal;">'cython_'</span><span> </span><span>+</span><span> </span><span>name</span><span>[</span><span style="color: #004e82;">6</span><span>:])</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span style="color: purple;">return</span><span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span style="color: blue;">__getattr__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>)</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: blue;">__setattr__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>value</span><span>):</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>name</span><span>[:</span><span style="color: #004e82;">6</span><span>]</span><span> </span><span>==</span><span> </span><span style="color: teal;">'pyrex_'</span><span>:</span>
<span> </span><span style="color: purple;">return</span><span> </span><span style="color: blue;">setattr</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span style="color: teal;">'cython_'</span><span> </span><span>+</span><span> </span><span>name</span><span>[</span><span style="color: #004e82;">6</span><span>:],</span><span> </span><span>value</span><span>)</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span style="color: green;"># _build_ext.build_ext.__setattr__(self, name, value)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span style="color: blue;">__dict__</span><span>[</span><span>name</span><span>]</span><span> </span><span>=</span><span> </span><span>value</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: #0000b0;">finalize_options</span><span> </span><span>(</span><span style="color: purple;">self</span><span>):</span>
<span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span style="color: #0000b0;">finalize_options</span><span>(</span><span style="color: purple;">self</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span> </span><span style="color: purple;">is</span><span> </span><span style="color: blue;">None</span><span>:</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span> </span><span>=</span><span> </span><span>[]</span>
<span> </span><span style="color: purple;">elif</span><span> </span><span style="color: #0000b0;">isinstance</span><span>(</span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span>,</span><span> </span><span style="color: blue;">str</span><span>):</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span> </span><span>=</span><span> \</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span><span>.</span><span style="color: #0000b0;">split</span><span>(</span><span>os</span><span>.</span><span>pathsep</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span><span> </span><span style="color: purple;">is</span><span> </span><span style="color: blue;">None</span><span>:</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span><span> </span><span>=</span><span> </span><span>{}</span>
<span> </span><span style="color: green;"># finalize_options ()</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: #0000b0;">run</span><span>(</span><span style="color: purple;">self</span><span>):</span>
<span> </span><span style="color: green;"># We have one shot at this before build_ext initializes the compiler.</span>
<span> </span><span style="color: green;"># If --pyrex-gdb is in effect as a command line option or as option</span>
<span> </span><span style="color: green;"># of any Extension module, disable optimization for the C or C++</span>
<span> </span><span style="color: green;"># compiler.</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gdb</span><span> </span><span style="color: purple;">or</span><span> </span><span>[</span><span style="color: #004e82;">1</span><span> </span><span style="color: purple;">for</span><span> </span><span>ext</span><span> </span><span style="color: purple;">in</span><span> </span><span style="color: purple;">self</span><span>.</span><span>extensions</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>ext</span><span>,</span><span> </span><span style="color: teal;">'cython_gdb'</span><span>,</span><span> </span><span style="color: blue;">False</span><span>)]:</span>
<span> </span><span>optimization</span><span>.</span><span style="color: #0000b0;">disable_optimization</span><span>()</span>
<span> </span><span>_build_ext</span><span>.</span><span>build_ext</span><span>.</span><span style="color: #0000b0;">run</span><span>(</span><span style="color: purple;">self</span><span>)</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: #0000b0;">build_extensions</span><span>(</span><span style="color: purple;">self</span><span>):</span>
<span> </span><span style="color: green;"># First, sanity-check the 'extensions' list</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span style="color: #0000b0;">check_extensions_list</span><span>(</span><span style="color: purple;">self</span><span>.</span><span>extensions</span><span>)</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>ext</span><span> </span><span style="color: purple;">in</span><span> </span><span style="color: purple;">self</span><span>.</span><span>extensions</span><span>:</span>
<span> </span><span>ext</span><span>.</span><span>sources</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span style="color: #0000b0;">cython_sources</span><span>(</span><span>ext</span><span>.</span><span>sources</span><span>,</span><span> </span><span>ext</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span style="color: #0000b0;">build_extension</span><span>(</span><span>ext</span><span>)</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: #0000b0;">cython_sources</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>sources</span><span>,</span><span> </span><span>extension</span><span>):</span>
<span> </span><span style="color: teal;">"""</span>
<span style="color: teal;"> Walk the list of source files in 'sources', looking for Cython</span>
<span style="color: teal;"> source files (.pyx and .py). Run Cython on all that are</span>
<span style="color: teal;"> found, and return a modified 'sources' list with Cython source</span>
<span style="color: teal;"> files replaced by the generated C (or C++) files.</span>
<span style="color: teal;"> """</span>
<span> </span><span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Compiler</span><span>.</span><span>Main</span><span> \</span>
<span> </span><span style="color: purple;">import</span><span> </span><span>CompilationOptions</span><span>,</span><span> \</span>
<span> </span><span>default_options</span><span> </span><span style="color: purple;">as</span><span> </span><span>cython_default_options</span><span>,</span><span> \</span>
<span> </span><span style="color: blue;">compile</span><span> </span><span style="color: purple;">as</span><span> </span><span>cython_compile</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Compiler</span><span>.</span><span>Errors</span><span> </span><span style="color: purple;">import</span><span> </span><span>PyrexError</span>
<span> </span><span style="color: purple;">except</span><span> </span><span style="color: blue;">ImportError</span><span>:</span>
<span> </span><span>e</span><span> </span><span>=</span><span> </span><span style="color: blue;">sys</span><span>.</span><span style="color: #0000b0;">exc_info</span><span>()[</span><span style="color: #004e82;">1</span><span>]</span>
<span> </span><span style="color: purple;">print</span><span>((</span><span style="color: teal;">"failed to import Cython: %s"</span><span> </span><span>%</span><span> </span><span>e</span><span>))</span>
<span> </span><span style="color: purple;">raise</span><span> </span><span style="color: #0000b0;">DistutilsPlatformError</span><span>(</span><span style="color: teal;">"Cython does not appear to be installed"</span><span>)</span>
<span> </span><span>new_sources</span><span> </span><span>=</span><span> </span><span>[]</span>
<span> </span><span>cython_sources</span><span> </span><span>=</span><span> </span><span>[]</span>
<span> </span><span>cython_targets</span><span> </span><span>=</span><span> </span><span>{}</span>
<span> </span><span style="color: green;"># Setup create_list and cplus from the extension options if</span>
<span> </span><span style="color: green;"># Cython.Distutils.extension.Extension is used, otherwise just</span>
<span> </span><span style="color: green;"># use what was parsed from the command-line or the configuration file.</span>
<span> </span><span style="color: green;"># cplus will also be set to true is extension.language is equal to</span>
<span> </span><span style="color: green;"># 'C++' or 'c++'.</span>
<span> </span><span style="color: green;">#try:</span>
<span> </span><span style="color: green;"># create_listing = self.cython_create_listing or \</span>
<span> </span><span style="color: green;"># extension.cython_create_listing</span>
<span> </span><span style="color: green;"># cplus = self.cython_cplus or \</span>
<span> </span><span style="color: green;"># extension.cython_cplus or \</span>
<span> </span><span style="color: green;"># (extension.language != None and \</span>
<span> </span><span style="color: green;"># extension.language.lower() == 'c++')</span>
<span> </span><span style="color: green;">#except AttributeError:</span>
<span> </span><span style="color: green;"># create_listing = self.cython_create_listing</span>
<span> </span><span style="color: green;"># cplus = self.cython_cplus or \</span>
<span> </span><span style="color: green;"># (extension.language != None and \</span>
<span> </span><span style="color: green;"># extension.language.lower() == 'c++')</span>
<span> </span><span>create_listing</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_create_listing</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_create_listing'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>line_directives</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_line_directives</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_line_directives'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>no_c_in_traceback</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>no_c_in_traceback</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'no_c_in_traceback'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>cplus</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_cplus</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_cplus'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span>(</span><span>extension</span><span>.</span><span>language</span><span> </span><span style="color: purple;">and</span><span> </span><span>extension</span><span>.</span><span>language</span><span>.</span><span style="color: #0000b0;">lower</span><span>()</span><span> </span><span>==</span><span> </span><span style="color: teal;">'c++'</span><span>)</span>
<span> </span><span>cython_gen_pxi</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gen_pxi</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_gen_pxi'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)</span>
<span> </span><span>cython_gdb</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_gdb</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_gdb'</span><span>,</span><span> </span><span style="color: blue;">False</span><span>)</span>
<span> </span><span>cython_compile_time_env</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_compile_time_env</span><span> </span><span style="color: purple;">or</span><span> \</span>
<span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_compile_time_env'</span><span>,</span><span> </span><span style="color: blue;">None</span><span>)</span>
<span> </span><span style="color: green;"># Set up the include_path for the Cython compiler:</span>
<span> </span><span style="color: green;"># 1. Start with the command line option.</span>
<span> </span><span style="color: green;"># 2. Add in any (unique) paths from the extension</span>
<span> </span><span style="color: green;"># cython_include_dirs (if Cython.Distutils.extension is used).</span>
<span> </span><span style="color: green;"># 3. Add in any (unique) paths from the extension include_dirs</span>
<span> </span><span>includes</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_include_dirs</span>
<span> </span><span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>extension</span><span>.</span><span>cython_include_dirs</span><span>:</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>includes</span><span>:</span>
<span> </span><span>includes</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>i</span><span>)</span>
<span> </span><span style="color: purple;">except</span><span> </span><span style="color: blue;">AttributeError</span><span>:</span>
<span> </span><span style="color: purple;">pass</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>extension</span><span>.</span><span>include_dirs</span><span>:</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>i</span><span> </span><span style="color: purple;">in</span><span> </span><span>includes</span><span>:</span>
<span> </span><span>includes</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>i</span><span>)</span>
<span> </span><span style="color: green;"># Set up Cython compiler directives:</span>
<span> </span><span style="color: green;"># 1. Start with the command line option.</span>
<span> </span><span style="color: green;"># 2. Add in any (unique) entries from the extension</span>
<span> </span><span style="color: green;"># cython_directives (if Cython.Distutils.extension is used).</span>
<span> </span><span>directives</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>cython_directives</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: blue;">hasattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">"cython_directives"</span><span>):</span>
<span> </span><span>directives</span><span>.</span><span style="color: #0000b0;">update</span><span>(</span><span>extension</span><span>.</span><span>cython_directives</span><span>)</span>
<span> </span><span style="color: green;"># Set the target_ext to '.c'. Cython will change this to '.cpp' if</span>
<span> </span><span style="color: green;"># needed.</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>cplus</span><span>:</span>
<span> </span><span>target_ext</span><span> </span><span>=</span><span> </span><span style="color: teal;">'.cpp'</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span>target_ext</span><span> </span><span>=</span><span> </span><span style="color: teal;">'.c'</span>
<span> </span><span style="color: green;"># Decide whether to drop the generated C files into the temp dir</span>
<span> </span><span style="color: green;"># or the source tree.</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span style="color: purple;">self</span><span>.</span><span>inplace</span><span> </span><span style="color: purple;">and</span><span> </span><span>(</span><span style="color: purple;">self</span><span>.</span><span>cython_c_in_temp</span>
<span> </span><span style="color: purple;">or</span><span> </span><span style="color: blue;">getattr</span><span>(</span><span>extension</span><span>,</span><span> </span><span style="color: teal;">'cython_c_in_temp'</span><span>,</span><span> </span><span style="color: #004e82;">0</span><span>)):</span>
<span> </span><span>target_dir</span><span> </span><span>=</span><span> </span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">join</span><span>(</span><span style="color: purple;">self</span><span>.</span><span>build_temp</span><span>,</span><span> </span><span style="color: teal;">"pyrex"</span><span>)</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>package_name</span><span> </span><span style="color: purple;">in</span><span> </span><span>extension</span><span>.</span><span>name</span><span>.</span><span style="color: #0000b0;">split</span><span>(</span><span style="color: teal;">'.'</span><span>)[:</span><span>-</span><span style="color: #004e82;">1</span><span>]:</span>
<span> </span><span>target_dir</span><span> </span><span>=</span><span> </span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">join</span><span>(</span><span>target_dir</span><span>,</span><span> </span><span>package_name</span><span>)</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span>target_dir</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span>
<span> </span><span>newest_dependency</span><span> </span><span>=</span><span> </span><span style="color: blue;">None</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>source</span><span> </span><span style="color: purple;">in</span><span> </span><span>sources</span><span>:</span>
<span> </span><span>(</span><span>base</span><span>,</span><span> </span><span>ext</span><span>)</span><span> </span><span>=</span><span> </span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">splitext</span><span>(</span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">basename</span><span>(</span><span>source</span><span>))</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>ext</span><span> </span><span>==</span><span> </span><span style="color: teal;">".py"</span><span>:</span>
<span> </span><span style="color: green;"># FIXME: we might want to special case this some more</span>
<span> </span><span>ext</span><span> </span><span>=</span><span> </span><span style="color: teal;">'.pyx'</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>ext</span><span> </span><span>==</span><span> </span><span style="color: teal;">".pyx"</span><span>:</span><span> </span><span style="color: green;"># Cython source file</span>
<span> </span><span>output_dir</span><span> </span><span>=</span><span> </span><span>target_dir</span><span> </span><span style="color: purple;">or</span><span> </span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">dirname</span><span>(</span><span>source</span><span>)</span>
<span> </span><span>new_sources</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">join</span><span>(</span><span>output_dir</span><span>,</span><span> </span><span>base</span><span> </span><span>+</span><span> </span><span>target_ext</span><span>))</span>
<span> </span><span>cython_sources</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>source</span><span>)</span>
<span> </span><span>cython_targets</span><span>[</span><span>source</span><span>]</span><span> </span><span>=</span><span> </span><span>new_sources</span><span>[</span><span>-</span><span style="color: #004e82;">1</span><span>]</span>
<span> </span><span style="color: purple;">elif</span><span> </span><span>ext</span><span> </span><span>==</span><span> </span><span style="color: teal;">'.pxi'</span><span> </span><span style="color: purple;">or</span><span> </span><span>ext</span><span> </span><span>==</span><span> </span><span style="color: teal;">'.pxd'</span><span>:</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>newest_dependency</span><span> </span><span style="color: purple;">is</span><span> </span><span style="color: blue;">None</span><span> \</span>
<span> </span><span style="color: purple;">or</span><span> </span><span style="color: #0000b0;">newer</span><span>(</span><span>source</span><span>,</span><span> </span><span>newest_dependency</span><span>):</span>
<span> </span><span>newest_dependency</span><span> </span><span>=</span><span> </span><span>source</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span>new_sources</span><span>.</span><span style="color: blue;">append</span><span>(</span><span>source</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>cython_sources</span><span>:</span>
<span> </span><span style="color: purple;">return</span><span> </span><span>new_sources</span>
<span> </span><span>module_name</span><span> </span><span>=</span><span> </span><span>extension</span><span>.</span><span>name</span>
<span> </span><span style="color: purple;">for</span><span> </span><span>source</span><span> </span><span style="color: purple;">in</span><span> </span><span>cython_sources</span><span>:</span>
<span> </span><span>target</span><span> </span><span>=</span><span> </span><span>cython_targets</span><span>[</span><span>source</span><span>]</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>[</span><span>source</span><span>]</span><span> </span><span>+</span><span> </span><span style="color: #0000b0;">list</span><span>(</span><span>extension</span><span>.</span><span>depends</span><span> </span><span style="color: purple;">or</span><span> </span><span>())</span>
<span> </span><span style="color: purple;">if</span><span>(</span><span>source</span><span>[</span><span>-</span><span style="color: #004e82;">4</span><span>:].</span><span style="color: #0000b0;">lower</span><span>()</span><span>==</span><span style="color: teal;">".pyx"</span><span> </span><span style="color: purple;">and</span><span> </span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">isfile</span><span>(</span><span>source</span><span>[:</span><span>-</span><span style="color: #004e82;">3</span><span>]</span><span>+</span><span style="color: teal;">"pxd"</span><span>)):</span>
<span> </span><span>depends</span><span> </span><span>+</span><span>=</span><span> </span><span>[</span><span>source</span><span>[:</span><span>-</span><span style="color: #004e82;">3</span><span>]</span><span>+</span><span style="color: teal;">"pxd"</span><span>]</span>
<span> </span><span style="font-size: large;"><b><span>rebuild</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>force</span><span> </span><span style="color: purple;">or</span><span> </span><span style="color: #0000b0;">newer_group</span><span>(</span><span>depends</span><span>,</span><span> </span><span>target</span><span>,</span><span> </span><span style="color: teal;">'newer'</span><span>)</span></b></span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">not</span><span> </span><span>rebuild</span><span> </span><span style="color: purple;">and</span><span> </span><span>newest_dependency</span><span> </span><span style="color: purple;">is</span><span> </span><span style="color: purple;">not</span><span> </span><span style="color: blue;">None</span><span>:</span>
<span> </span><span>rebuild</span><span> </span><span>=</span><span> </span><span style="color: #0000b0;">newer</span><span>(</span><span>newest_dependency</span><span>,</span><span> </span><span>target</span><span>)</span>
<span> </span><span style="color: purple;">if</span><span> </span><span>rebuild</span><span>:</span>
<span> </span><span>log</span><span>.</span><span style="color: #0000b0;">info</span><span>(</span><span style="color: teal;">"cythoning %s to %s"</span><span>,</span><span> </span><span>source</span><span>,</span><span> </span><span>target</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span style="color: #0000b0;">mkpath</span><span>(</span><span>os</span><span>.</span><span style="color: blue;">path</span><span>.</span><span style="color: #0000b0;">dirname</span><span>(</span><span>target</span><span>))</span>
<span> </span><span style="color: purple;">if</span><span> </span><span style="color: purple;">self</span><span>.</span><span>inplace</span><span>:</span>
<span> </span><span>output_dir</span><span> </span><span>=</span><span> </span><span>os</span><span>.</span><span>curdir</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span>output_dir</span><span> </span><span>=</span><span> </span><span style="color: purple;">self</span><span>.</span><span>build_lib</span>
<span> </span><span>options</span><span> </span><span>=</span><span> </span><span style="color: #0000b0;">CompilationOptions</span><span>(</span><span>cython_default_options</span><span>,</span>
<span> </span><span>use_listing_file</span><span> </span><span>=</span><span> </span><span>create_listing</span><span>,</span>
<span> </span><span>include_path</span><span> </span><span>=</span><span> </span><span>includes</span><span>,</span>
<span> </span><span>compiler_directives</span><span> </span><span>=</span><span> </span><span>directives</span><span>,</span>
<span> </span><span>output_file</span><span> </span><span>=</span><span> </span><span>target</span><span>,</span>
<span> </span><span>cplus</span><span> </span><span>=</span><span> </span><span>cplus</span><span>,</span>
<span> </span><span>emit_linenums</span><span> </span><span>=</span><span> </span><span>line_directives</span><span>,</span>
<span> </span><span>c_line_in_traceback</span><span> </span><span>=</span><span> </span><span style="color: purple;">not</span><span> </span><span>no_c_in_traceback</span><span>,</span>
<span> </span><span>generate_pxi</span><span> </span><span>=</span><span> </span><span>cython_gen_pxi</span><span>,</span>
<span> </span><span>output_dir</span><span> </span><span>=</span><span> </span><span>output_dir</span><span>,</span>
<span> </span><span>gdb_debug</span><span> </span><span>=</span><span> </span><span>cython_gdb</span><span>,</span>
<span> </span><span>compile_time_env</span><span> </span><span>=</span><span> </span><span>cython_compile_time_env</span><span>)</span>
<span> </span><span>result</span><span> </span><span>=</span><span> </span><span style="color: #0000b0;">cython_compile</span><span>(</span><span>source</span><span>,</span><span> </span><span>options</span><span>=</span><span>options</span><span>,</span>
<span> </span><span>full_module_name</span><span>=</span><span>module_name</span><span>)</span>
<span> </span><span style="color: purple;">else</span><span>:</span>
<span> </span><span>log</span><span>.</span><span style="color: #0000b0;">info</span><span>(</span><span style="color: teal;">"skipping '%s' Cython extension (up-to-date)"</span><span>,</span><span> </span><span>target</span><span>)</span>
<span> </span><span style="color: purple;">return</span><span> </span><span>new_sources</span></pre>
</div>
<br />
Note the enlarged, bolded line. I have not been able to find any mechanism by which a parameter to Cython.Distutils.extension.Extension.__init__(..) can cause Cython.Distutils.build_ext.force to be set. Additionally, distutils instantiates build_ext for us, denying us the opportunity to modify build_ext.force before use but after instantiation. However, we may derive our own, customized build_ext:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>core</span><span> </span><span style="color: purple;">import</span><span> </span><span>setup</span>
<span style="color: purple;">import</span><span> </span><span>numpy</span>
<span style="color: purple;">import</span><span> </span><span>os</span>
<span style="color: purple;">import</span><span> </span><span>subprocess</span>
<span style="color: purple;">import</span><span> </span><span style="color: blue;">sys</span>
<span>cpp_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics_impl.cpp'</span>
<span>cython_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.pyx'</span>
<span>cythoned_source</span><span> </span><span>=</span><span> </span><span style="color: teal;">'cython/_ndimage_statistics.cpp'</span>
<span>cython_source_deps</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: teal;">'cython/_ndimage_statistics_impl.h'</span><span>]</span>
<span>include_dirs</span><span> </span><span>=</span><span> </span><span>[</span><span>numpy</span><span>.</span><span style="color: #0000b0;">get_include</span><span>()]</span>
<span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>extra_link_args</span><span> </span><span>=</span><span> </span><span>[]</span>
<span>define_macros</span><span> </span><span>=</span><span> </span><span>[]</span>
<span style="color: purple;">if</span><span> </span><span style="color: blue;">sys</span><span>.</span><span>platform</span><span> </span><span>!=</span><span> </span><span style="color: teal;">'win32'</span><span>:</span>
<span> </span><span>extra_compile_args</span><span>.</span><span style="color: #0000b0;">extend</span><span>((</span><span style="color: teal;">'-O3'</span><span>,</span><span> </span><span style="color: teal;">'-march=native'</span><span>))</span>
<span style="color: purple;">try</span><span>:</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span> </span><span style="color: purple;">import</span><span> </span><span>build_ext</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>Cython</span><span>.</span><span>Distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<b>
<span> </span><span style="color: purple;">class</span><span> </span><span style="color: #0000b0;">build_ext_forced_rebuild</span><span>(</span><span>build_ext</span><span>):</span>
<span> </span><span style="color: purple;">def</span><span> </span><span style="color: blue;">__init__</span><span>(</span><span style="color: purple;">self</span><span>,</span><span> </span><span>*</span><span>va</span><span>,</span><span> </span><span>**</span><span>ka</span><span>):</span>
<span> </span><span style="color: #0000b0;">super</span><span>().</span><span style="color: blue;">__init__</span><span>(</span><span>*</span><span>va</span><span>,</span><span> </span><span>**</span><span>ka</span><span>)</span>
<span> </span><span style="color: purple;">self</span><span>.</span><span>force</span><span> </span><span>=</span><span> </span><span style="color: blue;">True</span></b>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cython_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span><span>,</span>
<span> </span><span>cython_directives</span><span>={</span><span style="color: teal;">'language_level'</span><span> </span><span>:</span><span> </span><span style="color: #004e82;">3</span><span>}</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>cmdclass</span><span> </span><span>=</span><span> </span><span>{</span><span style="color: teal;">'build_ext'</span><span> </span><span>:</span><span> </span><span>build_ext_forced_rebuild</span><span>},</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span>
<span style="color: purple;">except</span><span> </span><span style="color: blue;">ImportError</span><span>:</span>
<span> </span><span style="color: purple;">print</span><span>(</span><span style="color: teal;">'Cython does not appear to be installed. Attempting to use pre-made cpp file...'</span><span>)</span>
<span> </span><span style="color: purple;">from</span><span> </span><span>distutils</span><span>.</span><span>extension</span><span> </span><span style="color: purple;">import</span><span> </span><span>Extension</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>[</span><span style="color: #0000b0;">Extension</span><span>(</span><span style="color: teal;">'_ndimage_statistics'</span><span>,</span>
<span> </span><span>sources</span><span> </span><span>=</span><span> </span><span>[</span><span>cythoned_source</span><span>,</span><span> </span><span>cpp_source</span><span>],</span>
<span> </span><span>include_dirs</span><span> </span><span>=</span><span> </span><span>include_dirs</span><span>,</span>
<span> </span><span>define_macros</span><span> </span><span>=</span><span> </span><span>define_macros</span><span>,</span>
<span> </span><span>language</span><span> </span><span>=</span><span> </span><span style="color: teal;">'c++'</span><span>,</span>
<span> </span><span>depends</span><span> </span><span>=</span><span> </span><span>cython_source_deps</span><span>,</span>
<span> </span><span>extra_compile_args</span><span> </span><span>=</span><span> </span><span>extra_compile_args</span><span>,</span>
<span> </span><span>extra_link_args</span><span> </span><span>=</span><span> </span><span>extra_link_args</span>
<span> </span><span>)]</span>
<span> </span><span style="color: #0000b0;">setup</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span style="color: teal;">'ris_widget'</span><span>,</span>
<span> </span><span>ext_modules</span><span> </span><span>=</span><span> </span><span>ext_modules</span><span>)</span></pre>
</div>
<br />
Note the bolded section. Does this work?<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">[12:58 PM][ehvatum@pincuslab-scope:~/zplrepo/ris_widget]> python setup.py build_ext --inplace<br />running build_ext<br />cythoning cython/_ndimage_statistics.pyx to cython/_ndimage_statistics.cpp<br />building '_ndimage_statistics' extension<br />x86_64-pc-linux-gnu-g++ -pthread -fPIC -I/usr/lib64/python3.4/site-packages/numpy/core/include -I/usr/include/python3.4 -c cython/_ndimage_statistics.cpp -o build/temp.linux-x86_64-3.4/cython/_ndimage_statistics.o -O3 -march=native<br />In file included from /usr/lib64/python3.4/site-packages/numpy/core/include/numpy/ndarraytypes.h:1804:0,<br /> from /usr/lib64/python3.4/site-packages/numpy/core/include/numpy/ndarrayobject.h:17,<br /> from /usr/lib64/python3.4/site-packages/numpy/core/include/numpy/arrayobject.h:4,<br /> from cython/_ndimage_statistics.cpp:239:<br />/usr/lib64/python3.4/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]<br /> #warning "Using deprecated NumPy API, disable it by " \<br /> ^<br />x86_64-pc-linux-gnu-g++ -pthread -fPIC -I/usr/lib64/python3.4/site-packages/numpy/core/include -I/usr/include/python3.4 -c cython/_ndimage_statistics_impl.cpp -o build/temp.linux-x86_64-3.4/cython/_ndimage_statistics_impl.o -O3 -march=native<br />x86_64-pc-linux-gnu-g++ -pthread -shared build/temp.linux-x86_64-3.4/cython/_ndimage_statistics.o build/temp.linux-x86_64-3.4/cython/_ndimage_statistics_impl.o -L/usr/lib64 -lpython3.4 -o /home/ehvatum/zplrepo/ris_widget/_ndimage_statistics.cpython-34.so</span></span><br />
<br />
Yes, finally, at long last, it does. I suppose it would have been easier to have made a Python call to unlink (delete) the generated .cpp if I wanted it rebuilt. But, I'm using distutils to build, aren't I? And, a build system should be capable of rebuilding, should it not? Sadly, all build systems are terrible, and distutils isn't actually so bad in comparison to many that I have used. The little bit of hackery I have under my belt now will be invaluable if I ever need to deal with distutils or distutils + Cython again.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com2tag:blogger.com,1999:blog-4636329550025284673.post-63930729346642771572015-03-04T23:41:00.000+01:002015-03-04T23:44:37.189+01:00Rendering a QGraphicsScene Directly to a Numpy Array with PyQt5 for Streaming MPEG-4 Encoding with FFmpegQt5's QGraphicsScene, QGraphicsItem, QGraphicsView, and associated classes - together called the "graphics view framework" - are <a href="http://doc.qt.io/qt-5/examples-graphicsview.html">quite powerful</a>. They are also fully exposed by PyQt5. Even rendering a QGraphicsScene directly to a numpy.ndarray works, and without requiring associating a QGraphicsView with the scene! However, knowing a bit about Qt, C++, Python, Numpy, ctypes, and sip is required to figure this out, which is asking a lot, and probably explains why this trick isn't seen more often.<br />
<br />
Transcript of an IPython terminal session demonstrating direct QGraphicsScene to Numpy array rendering:<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre>In [<span style="color: #004e82;">1</span>]: <span style="color: purple;">from</span> PyQt5 <span style="color: purple;">import</span> Qt
In [<span style="color: #004e82;">2</span>]: %gui qt
Out[<span style="color: #004e82;">2</span>]: <PyQt5.QtWidgets.QApplication at <span style="color: #004e82;">0x10e94f9d8</span>>
In [<span style="color: #004e82;">3</span>]: gs = Qt.<span style="color: #0000b0;">QGraphicsScene</span>()
In [<span style="color: #004e82;">4</span>]: gs.<span style="color: #0000b0;">addRect</span>(<span style="color: #004e82;">10</span>, <span style="color: #004e82;">10</span>, <span style="color: #004e82;">100</span>, <span style="color: #004e82;">200</span>, Qt.<span style="color: #0000b0;">QPen</span>(Qt.<span style="color: #0000b0;">QColor</span>(Qt.Qt.red)), Qt.<span style="color: #0000b0;">QBrush</span>(Qt.<span style="color: #0000b0;">QColor</span>(Qt.Qt.blue)))
Out[<span style="color: #004e82;">4</span>]: <PyQt5.QtWidgets.QGraphicsRectItem at <span style="color: #004e82;">0x11e473e58</span>>
In [<span style="color: #004e82;">5</span>]: gs.<span style="color: #0000b0;">addText</span>(<span style="color: teal;">'hello world'</span>)
Out[<span style="color: #004e82;">5</span>]: <PyQt5.QtWidgets.QGraphicsTextItem at <span style="color: #004e82;">0x11d81d9d8</span>>
In [<span style="color: #004e82;">6</span>]: _5.<span style="color: #0000b0;">moveBy</span>(<span style="color: #004e82;">50</span>,<span style="color: #004e82;">50</span>)
In [<span style="color: #004e82;">7</span>]: image = numpy.<span style="color: #0000b0;">zeros</span>((<span style="color: #004e82;">600</span>,<span style="color: #004e82;">800</span>,<span style="color: #004e82;">3</span>),dtype=numpy.uint8)
In [<span style="color: #004e82;">8</span>]: gs.<span style="color: #0000b0;">setBackgroundBrush</span>(Qt.<span style="color: #0000b0;">QBrush</span>(Qt.Qt.black))
In [<span style="color: #004e82;">9</span>]: <span style="color: purple;">import</span> sip
In [<span style="color: #004e82;">10</span>]: <span style="color: purple;">import</span> skimage.io <span style="color: purple;">as</span> skio
In [<span style="color: #004e82;">11</span>]: plt.<span style="color: #0000b0;">ion</span>()
In [<span style="color: #004e82;">12</span>]: qimage = Qt.<span style="color: #0000b0;">QImage</span>(sip.<span style="color: #0000b0;">voidptr</span>(image.ctypes.data), <span style="color: #004e82;">800</span>, <span style="color: #004e82;">600</span>, Qt.QImage.Format_RGB888)
In [<span style="color: #004e82;">13</span>]: qpainter = Qt.<span style="color: #0000b0;">QPainter</span>()
In [<span style="color: #004e82;">14</span>]: qpainter.<span style="color: #0000b0;">begin</span>(qimage)
Out[<span style="color: #004e82;">14</span>]: <span style="color: blue;">True</span>
In [<span style="color: #004e82;">15</span>]: qpainter.<span style="color: #0000b0;">setRenderHint</span>(Qt.QPainter.Antialiasing)
In [<span style="color: #004e82;">16</span>]: gs.<span style="color: #0000b0;">render</span>(qpainter)
In [<span style="color: #004e82;">17</span>]: qpainter.<span style="color: #0000b0;">end</span>()
Out[<span style="color: #004e82;">17</span>]: <span style="color: blue;">True</span>
In [<span style="color: #004e82;">18</span>]: skio.<span style="color: #0000b0;">imshow</span>(image)
</pre>
</div>
<br />
This has proven useful for procedural video composition in a research setting (eg, development and testing of computer vision algorithms, visualization of deltas in time lapse images, and various other things where I need to overlay text, vector graphics, etc. over a series of images).<br />
<br />
Wrapping a QImage around an ndarray loaded by skimage.io or what-have-you is the same as wrapping a QImage around an ndarray you created manually:<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre>[<span style="color: #004e82;">04</span>:<span style="color: #004e82;">03</span> PM][ehvatum@pincuslab-<span style="color: #004e82;">2</span>:~/zplrepo]> ipython
Python <span style="color: #004e82;">3.4.2</span> (default, Oct <span style="color: #004e82;">22</span> <span style="color: #004e82;">2014</span>, <span style="color: #004e82;">12</span>:<span style="color: #004e82;">10</span>:<span style="color: #004e82;">46</span>)
Type <span style="color: teal;">"copyright"</span>, <span style="color: teal;">"credits"</span> <span style="color: purple;">or</span> <span style="color: teal;">"license"</span> <span style="color: purple;">for</span> more information.
IPython <span style="color: #004e82;">3.0.0</span>-dev -- An enhanced Interactive Python.
? -> Introduction <span style="color: purple;">and</span> overview of IPython<span style="color: teal;">'s features.</span>
<span style="color: teal;">%quickref -> Quick reference.</span>
<span style="color: teal;">help -> Python'</span>s own help system.
object? -> Details about <span style="color: teal;">'object'</span>, use <span style="color: teal;">'object??'</span> <span style="color: purple;">for</span> extra details.
In [<span style="color: #004e82;">1</span>]: <span style="color: purple;">from</span> PyQt5 <span style="color: purple;">import</span> Qt
In [<span style="color: #004e82;">2</span>]: %gui qt
Out[<span style="color: #004e82;">2</span>]: <PyQt5.QtWidgets.QApplication at <span style="color: #004e82;">0x10dc809d8</span>>
In [<span style="color: #004e82;">3</span>]: gs = Qt.<span style="color: #0000b0;">QGraphicsScene</span>()
In [<span style="color: #004e82;">4</span>]: <span style="color: purple;">import</span> skimage.io <span style="color: purple;">as</span> skio
In [<span style="color: #004e82;">5</span>]: loaded_image = skio.<span style="color: #0000b0;">imread</span>(<span style="color: teal;">'/Users/ehvatum/heic1015a.jpg'</span>)
In [<span style="color: #004e82;">6</span>]: loaded_image.shape
Out[<span style="color: #004e82;">6</span>]: (<span style="color: #004e82;">2006</span>, <span style="color: #004e82;">3924</span>, <span style="color: #004e82;">3</span>)
In [<span style="color: #004e82;">8</span>]: <span style="color: purple;">import</span> sip
In [<span style="color: #004e82;">9</span>]: gs.<span style="color: #0000b0;">addPixmap</span>(Qt.<span style="color: #0000b0;">QPixmap</span>(Qt.<span style="color: #0000b0;">QImage</span>(sip.<span style="color: #0000b0;">voidptr</span>(loaded_image.ctypes.data), <span style="color: #004e82;">3924</span>, <span style="color: #004e82;">2006</span>, Qt.QImage.Format_RGB888)))
Out[<span style="color: #004e82;">9</span>]: <PyQt5.QtWidgets.QGraphicsPixmapItem at <span style="color: #004e82;">0x114574b88</span>></pre>
</div>
<br />
Keep in mind that the QImage constructor's format argument must match the actual in-memory layout of the Numpy array you supplied. So, it won't work to feed in any sort of complicated view of an ndarray: if the array you wish to wrap in a QImage is not contiguous and aligned, make a copy that is contiguous and aligned with numpy.ascontiguousarray, and retain this copy while the QImage exists (QImage does not keep a reference to the supplied array, so you must if it is to avoid being garbage collected).<br />
<br />
For the next bit, streaming mpeg4 video encoding of the ndarrays that the QGraphicsScene rendered into, I use the <a href="https://github.com/Zulko/moviepy">moviepy</a> package:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">from</span> moviepy.video.io.ffmpeg_writer <span style="color: purple;">import</span> FFMPEG_VideoWriter
...
scene_rect = gs.<span style="color: #0000b0;">sceneRect</span>()
desired_size = scene_rect.<span style="color: #0000b0;">width</span>(), scene_rect.<span style="color: #0000b0;">height</span>()
<span style="color: green;"># Odd value width or height causes problems for some codecs</span>
<span style="color: purple;">if</span> desired_size[<span style="color: #004e82;">0</span>] % <span style="color: #004e82;">2</span>:
desired_size[<span style="color: #004e82;">0</span>] += <span style="color: #004e82;">1</span>
<span style="color: purple;">if</span> desired_size[<span style="color: #004e82;">1</span>] % <span style="color: #004e82;">2</span>:
desired_size[<span style="color: #004e82;">1</span>] += <span style="color: #004e82;">1</span>
buffer = numpy.<span style="color: #0000b0;">empty</span>((desired_size[<span style="color: #004e82;">1</span>], desired_size[<span style="color: #004e82;">0</span>], <span style="color: #004e82;">3</span>), dtype=numpy.uint8)
qbuffer = Qt.<span style="color: #0000b0;">QImage</span>(sip.<span style="color: #0000b0;">voidptr</span>(<span style="color: purple;">self</span>._buffer.ctypes.data), desired_size[<span style="color: #004e82;">0</span>], desired_size[<span style="color: #004e82;">1</span>], Qt.QImage.Format_RGB888)
ffmpeg_writer = <span style="color: #0000b0;">FFMPEG_VideoWriter</span>(<span style="color: blue;">str</span>(<span style="color: purple;">self</span>._fpath), desired_size, fps=<span style="color: #004e82;">10</span>, codec=<span style="color: teal;">'mpeg4'</span>, preset=<span style="color: teal;">'veryslow'</span>, bitrate=<span style="color: teal;">'15000k'</span>)
qpainter = Qt.<span style="color: #0000b0;">QPainter</span>()
<span style="color: purple;">for</span> i <span style="color: purple;">in</span> <span style="color: blue;">range</span>(frame_count):
<span style="color: #0000b0;">advance_scene_by_one_frame</span>(gs)
qpainter.<span style="color: #0000b0;">begin</span>(qbuffer)
qpainter.<span style="color: #0000b0;">setRenderHint</span>(Qt.QPainter.Antialiasing)
gs.<span style="color: #0000b0;">render</span>(qpainter)
qpainter.<span style="color: #0000b0;">end</span>()
ffmpeg_writer.<span style="color: #0000b0;">write_frame</span>(buffer)
ffmpeg_writer.<span style="color: blue;">close</span>()</pre>
</div>
<br />Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com1tag:blogger.com,1999:blog-4636329550025284673.post-5042604309199653902015-01-23T19:51:00.002+01:002015-01-23T19:51:50.742+01:00In PyQt5, with QOpenGlWidget, on OS X, with OpenGL 4.1 and format.setProfile(Qt.QSurfaceFormat.CoreProfile), how do I avoid crashing?YOU DON'T. Also, it's not PyQt5's fault; the following C++ code also causes the same crash for the same reason:<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: olive; font-weight: bolder;">#include</span> <qtcore>
<span style="color: olive; font-weight: bolder;">#include</span> <qtwidgets>
<span style="color: olive; font-weight: bolder;">#include</span> <qapplication>
<span style="color: purple;">class</span> GlWidget : <span style="color: purple;">public</span> QOpenGLWidget
{
<span style="color: purple;">public</span>:
<span style="color: #0000b0;">GlWidget</span>()
{
QSurfaceFormat f;
f.<span style="color: #0000b0;">setRenderableType</span>(QSurfaceFormat::OpenGL);
f.<span style="color: #0000b0;">setVersion</span>(<span style="color: #004e82;">4</span>,<span style="color: #004e82;">1</span>);
f.<span style="color: #0000b0;">setProfile</span>(QSurfaceFormat::CoreProfile);
f.<span style="color: #0000b0;">setSwapBehavior</span>(QSurfaceFormat::DoubleBuffer);
f.<span style="color: #0000b0;">setStereo</span>(<span style="color: purple;">false</span>);
<span style="color: #0000b0;">setFormat</span>(f);
}
<span style="color: purple;">virtual</span> <span style="color: purple;">void</span> <span style="color: #0000b0;">initializeGL</span>()
{
}
<span style="color: purple;">virtual</span> <span style="color: purple;">void</span> <span style="color: #0000b0;">paintGL</span>()
{
}
<span style="color: purple;">virtual</span> <span style="color: purple;">void</span> <span style="color: #0000b0;">resizeGL</span>(<span style="color: purple;">int</span> w, <span style="color: purple;">int</span> h)
{
}
};
<span style="color: purple;">int</span> <span style="color: #0000b0;">main</span>(<span style="color: purple;">int</span> argc, <span style="color: purple;">char</span>** argv)
{
QApplication <span style="color: #0000b0;">app</span>(argc, argv);
GlWidget* glw = <span style="color: purple;">new</span> <span style="color: #0000b0;">GlWidget</span>();
glw-><span style="color: #0000b0;">show</span>();
<span style="color: purple;">return</span> app.<span style="color: #0000b0;">exec</span>();
}</qapplication></qtwidgets></qtcore></pre>
</div>
<br />
Here is what the crash looks like (stack trace from the offending thread):<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Thread 0 Crashed:: Dispatch queue: com.apple.main-thread<br />0 libobjc.A.dylib 0x00007fff848a30dd objc_msgSend + 29<br />1 libqcocoa.dylib 0x00000001129839d3 QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext*) const + 83<br />2 org.qt-project.QtGui 0x000000010fce471a QOpenGLContext::create() + 74<br />3 org.qt-project.QtWidgets 0x000000010f65304d QOpenGLWidgetPrivate::initialize() + 141<br />4 org.qt-project.QtWidgets 0x000000010f653e1a QOpenGLWidget::resizeEvent(QResizeEvent*) + 58<br />5 org.qt-project.QtWidgets 0x000000010f6334e2 QWidget::event(QEvent*) + 2162<br />6 org.qt-project.QtWidgets 0x000000010f5f3dbb QApplicationPrivate::notify_helper(QObject*, QEvent*) + 251<br />7 org.qt-project.QtWidgets 0x000000010f5f7110 QApplication::notify(QObject*, QEvent*) + 8192<br />8 org.qt-project.QtCore 0x0000000110475fb3 QCoreApplication::notifyInternal(QObject*, QEvent*) + 115<br />9 org.qt-project.QtWidgets 0x000000010f62bf17 QWidgetPrivate::sendPendingMoveAndResizeEvents(bool, bool) + 327<br />10 org.qt-project.QtWidgets 0x000000010f631c1a QWidgetPrivate::show_helper() + 42<br />11 org.qt-project.QtWidgets 0x000000010f632a42 QWidget::setVisible(bool) + 1394<br />12 qt5glcrashtest 0x000000010f552963 main + 67<br />13 qt5glcrashtest 0x000000010f552914 start + 52</span></span><br />
<br />
Three important things to note:<br />
<ol>
<li>On OS X, with OpenGL compatibility profile, which allows calls deprecated by OpenGL 3, you are strictly limited to OpenGL 2.1</li>
<li>The QPainter related stuff supported by the widget-ness of QOpenGLWidget relies on deprecated OpenGL calls</li>
<li>In Qt5 (the logic responsible may reside at a lower level) on OS X, specifically requesting an OpenGL 4.1 context with compatibility profile results in an OpenGL 2.1 context. Specifically requesting 4.1 with core profile does result in a 4.1 context - one that does not support the deprecated calls.</li>
</ol>
In short, it's no surprise that QOpenGLWidget with a 4.1 core profile context on OS X fails in some way. The workaround is to chose to either use QOpenGL<b>Widget</b> with OpenGL 2.1 or QOpenGL<b>Window</b> with OpenGL 4.1. This deprives you of direct QPainter support, but it does not prevent you from making your own QPainter that draws to a buffer you then composite via OpenGL in your QOpenGLWindow-derived object. NB: if you want to make your QOpenGLWindow-derived object's window a child of a normal Qt widget that can be placed by the QLayout classes, you'll want to do something along the lines of:<br />
<ul>
<li>With PyQt5, <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">glwidget = Qt.QWidget.createWindowContainer(glwindow, None, Qt.Qt.Widget)</span></span></li>
<li>In C++: <span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">glwidget = <span class="pl-s3">QWidget::createWindowContainer</span>(glwindow, parent, Qt::Widget); </span></span></li>
</ul>
Incidentally, if you need to support OpenGLWindow with OpenGL 4.3 on OS X, then I have bad news for you. OS X does not support OpenGL 4.3. Apple makes approximately all of their money on iOS trash. Any money spent on OS X development is, by comparison, completely wasted. Don't hold your breath waiting for them to improve OS X. Instead, expect half-baked iOS features to appear in OS X quarter-baked. That is, at best, OS X might support some new OpenGL ES features, with a huge number of wont-fix bugs. Too bad, so sad, get a real OS.Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0tag:blogger.com,1999:blog-4636329550025284673.post-35285905854719649622014-10-21T16:37:00.001+02:002014-10-21T16:50:47.991+02:00Detecting None object in Python C APIThis is a day-one Python C API question that I have answered about a million times: "how do I detect the None value?"<br />
<br />
The answer I have always given is, "read the docs." Today, I got some huge push back on that.<br />
<br />
Quoth the Python docs to which I have referred:<br />
<h1>
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">The None Object</span></span></h1>
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">
</span></span>
<br />
<div id="index-0">
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">Note that the <a class="reference internal" href="https://docs.python.org/3/c-api/type.html#c.PyTypeObject" title="PyTypeObject"><span class="xref c c-type docutils literal"><span class="pre">PyTypeObject</span></span></a> for <span class="docutils literal"><span class="pre">None</span></span> is not directly exposed in the
Python/C API. Since <span class="docutils literal"><span class="pre">None</span></span> is a singleton, testing for object identity (using
<span class="docutils literal"><span class="pre">==</span></span> in C) is sufficient. There is no <span class="xref c c-func docutils literal"><span class="pre">PyNone_Check()</span></span> function for the
same reason.</span></span></div>
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">
</span></span>
<br />
<dl class="var">
<dt id="c.Py_None">
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;"><a class="reference internal" href="https://docs.python.org/3/c-api/structures.html#c.PyObject" title="PyObject">PyObject</a>* <span class="descname">Py_None</span></span></span></dt>
<dd><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">The Python <span class="docutils literal"><span class="pre">None</span></span> object, denoting lack of value. This object has no methods.
It needs to be treated just like any other object with respect to reference
counts.</span></span></dd></dl>
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">
</span></span>
<br />
<dl class="macro">
<dt id="c.Py_RETURN_NONE">
<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;"><span class="descname">Py_RETURN_NONE</span></span></span></dt>
<dd><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"><span style="font-size: small;">Properly handle returning <a class="reference internal" href="https://docs.python.org/3/c-api/none.html#c.Py_None" title="Py_None"><span class="xref c c-data docutils literal"><span class="pre">Py_None</span></span></a> from within a C function (that is,
increment the reference count of None and return it.)</span></span></dd></dl>
<br />
As you can see, the docs lay it all out. None is a global singleton and you need only test for object identity to distinguish it from not None. <br />
<br />
The push back: <i>"Err, singleton? Global, in what sense? ' Object identity'?? I'm a C programmer! We speak the same words, but yours are without meaning!"</i><br />
<br />
On second thought, the docs do not lay it out.<br />
<br />
There are two things you are absolutely sure to want to do with <i>None</i> values when interacting with the CPython C API. The section of the docs I pasted deals with None values in the context of the CPython C API. What are the two things you actually want to know when you read this section of the docs?<br />
<br />
<b><span style="font-size: x-large;">1: HOW TO RETURN NONE FROM C</span></b><br />
Call the Py_RETURN_NONE macro.<br />
<br />
<span style="font-size: x-large;"><b>2: HOW TO DETECT A NONE VALUE IN C</b></span><br />
<span style="font-size: normal;">There is no PyNone_Check() function, but testing for object identity is OK. So, test for identity:</span><br />
<br />
<pre>PyObject* blah(PyObject* foo){
if(foo == Py_None){
/* argument is None; let's return None */
Py_RETURN_NONE;
}else{
/* do something and return python object */
...
}
}</pre>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com1tag:blogger.com,1999:blog-4636329550025284673.post-41769980651244660212014-09-05T23:39:00.001+02:002014-09-05T23:56:48.756+02:00Getting PyQt5 Coroutines Without Dragging In Another Event LoopSuppose you are in the middle of implementing a big project in Python with PyQt5. You find yourself needing to perform consecutive asynchronous operations without blocking, and you want to avoid writing a state machine to pick up where you left off after each asynchronous operation completes.<br />
<br />
The most sensible representation of sequential asynchronous operations is no different than the most sensible representation of sequential synchronous operations: sequential calls within a function. This is accomplished by using coroutines.<br />
<br />
Ok, Python's new async library (Tulip) has coroutines. Not ok: Tulip's coroutines are dispatched by its own event loop.<br />
<br />
Ok, gevent has coroutines. Not ok: gevent coroutines are dispatched by gevent's event loop.<br />
<br />
Ok, this that and the other big fat framework has coroutines. Not ok: the same sad story of requiring an event loop that is not Qt's event loop!<br />
<br />
You could write a Qt event dispatcher in C++ enabling Qt to sit on someone else's event loop - for example, the event loop your async library obstinately insists upon having. This is a huge pain. Qt's event loop is perfectly fine. Another event loop is neither wanted nor needed. A whole raft of AsyncServer and Protocol classes and Sockets and Streams are neither wanted nor needed. Again, we're happy with Qt's event loop. We're happy with Qt's sockets. We're smitten with QSerialPort - it can signal me when data arrives on the port, which pyserial certainly can not. Can all these other event loops and networking classes please <i>get lost</i> and let me do my own coroutine dispatch upon Qt signal receipt?<br />
<br />
In fact, yes. Here's how to do it: use greenlets and dispatch them from your Qt slots. It works everywhere (even in IPython after doing %gui qt) it's easy to understand, it's easy to explain, it doesn't bring in another godforsaken event loop, and it takes only a few lines of code.<br />
<br />
Here's a worthlessly simple example from an interactive IPython command line session:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">In [1]: import greenlet<br /><br />In [2]: from PyQt5 import Qt<br /><br />In [3]: %gui qt<br />Out[3]: <pyqt5 .qtwidgets.qapplication="" 0x106c77f78="" at=""><br /><br />In [4]: button = Qt.QPushButton('resume')<br /><br />In [5]: button.show()<br /><br />In [6]: def f0():<br /> ...: print('kicking off an async operation. The async operation is waiting-for-you-to-press-button.')<br /> ...: greenlet.getcurrent().parent.switch()<br /> ...: print('ok, you have pressed the button. Press it again.')<br /> ...: greenlet.getcurrent().parent.switch()<br /> ...: print('and you pressed it again. I think we are done here.')<br /> ...: <br /><br />In [7]: g0 = greenlet.greenlet(f0)<br /><br />In [8]: def onPress():<br /> ...: g0.switch()<br /> ...: <br /><br />In [9]: button.clicked.connect(onPress)<br /><br />In [10]: g0.switch()<br />kicking off an async operation. The async operation is waiting-for-you-to-press-button.<br />Out[10]: ()<br /><br />In [11]: ok, you have pressed the button. Press it again.<br />and you pressed it again. I think we are done here.<br /><br /><br />In [11]: g0 = greenlet.greenlet(f0)<br /><br />In [12]: g0.switch()<br />kicking off an async operation. The async operation is waiting-for-you-to-press-button.<br />Out[12]: ()<br /><br />In [13]: 1+1<br />Out[13]: 2<br /><br />In [14]: 2+2<br />Out[14]: 4<br /><br />In [15]: print('hi mom')<br />hi mom<br /><br />In [16]: ok, you have pressed the button. Press it again.<br /><br /><br />In [16]: 3+3<br />Out[16]: 6<br /><br />In [17]: print('hi dad')<br />hi dad<br /><br />In [18]: and you pressed it again. I think we are done here.</pyqt5></span><br />
<br />
You may ask, "what is <span style="font-family: "Courier New",Courier,monospace;">greenlet.getcurrent().parent.switch()</span>doing?" It switches back to the implicit always extant greenlet that, thanks to the %gui qt command, is running the Qt event loop and associated input hook and whatnot. It doesn't matter what it's doing, really. Only that we switched back to it matters.<br />
<br />
Because there are only two kinds of example in this world, here's one of the second kind: a worthlessly over-complicated example. This one is meant to execute as a stand-alone program:<br />
<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre><span style="color: purple;">import</span> greenlet
<span style="color: purple;">from</span> PyQt5 <span style="color: purple;">import</span> Qt
<span style="color: purple;">import</span> <span style="color: blue;">sys</span>
<span style="color: purple;">from</span> acquisition.pedals.pedals <span style="color: purple;">import</span> Pedals
<span style="color: purple;">class</span> <span style="color: #0000b0;">WaitDialog</span>(Qt.QDialog):
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>, dialog, pedalIdx, mainGt):
<span style="color: #0000b0;">super</span>().<span style="color: blue;">__init__</span>(dialog)
<span style="color: purple;">self</span>._dialog = dialog
<span style="color: purple;">self</span>._pedalIdx = pedalIdx
<span style="color: purple;">self</span>._mainGt = mainGt
<span style="color: purple;">self</span>.<span style="color: #0000b0;">setWindowModality</span>(Qt.Qt.NonModal)
<span style="color: purple;">self</span>.<span style="color: #0000b0;">setWindowTitle</span>(<span style="color: teal;">'Green Qt Test'</span>)
<span style="color: purple;">self</span>.<span style="color: #0000b0;">setLayout</span>(Qt.<span style="color: #0000b0;">QVBoxLayout</span>())
<span style="color: purple;">self</span>.<span style="color: #0000b0;">layout</span>().<span style="color: #0000b0;">addWidget</span>(Qt.<span style="color: #0000b0;">QLabel</span>(<span style="color: teal;">'Waiting for pedal {} up...'</span>.<span style="color: #0000b0;">format</span>(<span style="color: purple;">self</span>._pedalIdx)))
<span style="color: purple;">self</span>._cancelBtn = Qt.<span style="color: #0000b0;">QPushButton</span>(<span style="color: teal;">'cancel'</span>)
<span style="color: purple;">self</span>.<span style="color: #0000b0;">layout</span>().<span style="color: #0000b0;">addWidget</span>(<span style="color: purple;">self</span>._cancelBtn)
<span style="color: purple;">self</span>._cancelBtn.clicked.<span style="color: #0000b0;">connect</span>(<span style="color: purple;">self</span>.cancel)
<span style="color: purple;">self</span>.waitForPedalGt = greenlet.<span style="color: #0000b0;">greenlet</span>(<span style="color: purple;">self</span>.waitForPedal)
<span style="color: purple;">def</span> <span style="color: #0000b0;">waitForPedal</span>(<span style="color: purple;">self</span>):
<span style="color: purple;">self</span>._dialog.pedalWaitBtns[<span style="color: purple;">self</span>._pedalIdx].<span style="color: #0000b0;">setEnabled</span>(<span style="color: blue;">False</span>)
<span style="color: purple;">if</span> <span style="color: purple;">self</span>._mainGt.<span style="color: #0000b0;">switch</span>():
Qt.QMessageBox.<span style="color: #0000b0;">information</span>(<span style="color: purple;">self</span>, <span style="color: teal;">'Green Qt Test'</span>, <span style="color: teal;">'Pedal {} up received.'</span>.<span style="color: #0000b0;">format</span>(<span style="color: purple;">self</span>._pedalIdx))
<span style="color: purple;">self</span>._dialog.pedalWaitBtns[<span style="color: purple;">self</span>._pedalIdx].<span style="color: #0000b0;">setEnabled</span>(<span style="color: blue;">True</span>)
<span style="color: purple;">self</span>._dialog.pedalWaitDlgs[<span style="color: purple;">self</span>._pedalIdx] = <span style="color: blue;">None</span>
<span style="color: purple;">self</span>.<span style="color: blue;">close</span>()
<span style="color: purple;">self</span>.<span style="color: #0000b0;">destroy</span>()
<span style="color: purple;">def</span> <span style="color: #0000b0;">cancel</span>(<span style="color: purple;">self</span>):
<span style="color: purple;">self</span>.waitForPedalGt.<span style="color: #0000b0;">switch</span>(<span style="color: blue;">False</span>)
<span style="color: purple;">class</span> <span style="color: #0000b0;">Dialog</span>(Qt.QDialog):
<span style="color: purple;">def</span> <span style="color: blue;">__init__</span>(<span style="color: purple;">self</span>, mainGt):
<span style="color: #0000b0;">super</span>().<span style="color: blue;">__init__</span>()
<span style="color: purple;">self</span>._mainGt = mainGt
<span style="color: purple;">self</span>.<span style="color: #0000b0;">setWindowTitle</span>(<span style="color: teal;">'Green Qt Test'</span>)
layout = Qt.<span style="color: #0000b0;">QVBoxLayout</span>()
<span style="color: purple;">self</span>.<span style="color: #0000b0;">setLayout</span>(layout)
<span style="color: purple;">self</span>.quitButton = Qt.<span style="color: #0000b0;">QPushButton</span>(<span style="color: teal;">'quit'</span>)
layout.<span style="color: #0000b0;">addWidget</span>(<span style="color: purple;">self</span>.quitButton)
<span style="color: purple;">self</span>.quitButton.clicked.<span style="color: #0000b0;">connect</span>(<span style="color: purple;">self</span>.<span style="color: blue;">close</span>)
<span style="color: purple;">self</span>.pedalWaitBtns = [<span style="color: blue;">None</span>, <span style="color: blue;">None</span>]
<span style="color: purple;">self</span>.pedalWaitDlgs = [<span style="color: blue;">None</span>, <span style="color: blue;">None</span>]
<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">0</span>] = Qt.<span style="color: #0000b0;">QPushButton</span>(<span style="color: teal;">'wait for pedal 0 up'</span>)
layout.<span style="color: #0000b0;">addWidget</span>(<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">0</span>])
<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">0</span>].clicked.<span style="color: #0000b0;">connect</span>(<span style="color: purple;">lambda</span>: <span style="color: purple;">self</span>.<span style="color: #0000b0;">pedalWaitBtnClickedSlot</span>(<span style="color: #004e82;">0</span>))
<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">1</span>] = Qt.<span style="color: #0000b0;">QPushButton</span>(<span style="color: teal;">'wait for pedal 1 up'</span>)
layout.<span style="color: #0000b0;">addWidget</span>(<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">1</span>])
<span style="color: purple;">self</span>.pedalWaitBtns[<span style="color: #004e82;">1</span>].clicked.<span style="color: #0000b0;">connect</span>(<span style="color: purple;">lambda</span>: <span style="color: purple;">self</span>.<span style="color: #0000b0;">pedalWaitBtnClickedSlot</span>(<span style="color: #004e82;">1</span>))
<span style="color: purple;">self</span>.pedals = <span style="color: #0000b0;">Pedals</span>()
<span style="color: purple;">self</span>.pedals.pedalUpChanged.<span style="color: #0000b0;">connect</span>(<span style="color: purple;">self</span>.pedalUpChangedSlot)
<span style="color: purple;">def</span> <span style="color: #0000b0;">pedalWaitBtnClickedSlot</span>(<span style="color: purple;">self</span>, pedalIdx):
<span style="color: purple;">if</span> <span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx] <span style="color: purple;">is</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx] = <span style="color: #0000b0;">WaitDialog</span>(<span style="color: purple;">self</span>, pedalIdx, <span style="color: purple;">self</span>._mainGt)
<span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx].<span style="color: #0000b0;">show</span>()
<span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx].waitForPedalGt.<span style="color: #0000b0;">switch</span>()
<span style="color: purple;">def</span> <span style="color: #0000b0;">pedalUpChangedSlot</span>(<span style="color: purple;">self</span>, pedalIdx, isUp):
<span style="color: purple;">if</span> isUp <span style="color: purple;">and</span> <span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx] <span style="color: purple;">is</span> <span style="color: purple;">not</span> <span style="color: blue;">None</span>:
<span style="color: purple;">self</span>.pedalWaitDlgs[pedalIdx].waitForPedalGt.<span style="color: #0000b0;">switch</span>(<span style="color: blue;">True</span>)
<span style="color: purple;">if</span> <span style="color: blue;">__name__</span> == <span style="color: teal;">'__main__'</span>:
app = Qt.<span style="color: #0000b0;">QApplication</span>(<span style="color: blue;">sys</span>.<span style="color: blue;">argv</span>)
<span style="color: purple;">def</span> <span style="color: #0000b0;">eventLoop</span>():
app.<span style="color: #0000b0;">exec_</span>()
eventLoopGt = greenlet.<span style="color: #0000b0;">greenlet</span>(eventLoop)
dialog = <span style="color: #0000b0;">Dialog</span>(eventLoopGt)
dialog.<span style="color: #0000b0;">show</span>()
eventLoopGt.<span style="color: #0000b0;">switch</span>() </pre>
</div>
<br />
Another worthlessly over-complicated example, this one meant to be run from within any context, including IPython interactive session:<br />
<br />
<div style="background-color: whitesmoke; color: black; font-style: normal; font-weight: normal; text-decoration: none;">
<pre class="sebg"><span class="se17">import</span><span class="se2"> </span><span class="se55">greenlet</span>
<span class="se17">import</span><span class="se2"> </span><span class="se55">numpy</span>
<span class="se17">from</span><span class="se2"> </span><span class="se55">PyQt5</span><span class="se2"> </span><span class="se17">import</span><span class="se2"> </span><span class="se55">Qt</span>
<span class="se17">import</span><span class="se2"> </span><span class="se24">sys</span>
<span class="se17">import</span><span class="se2"> </span><span class="se55">time</span>
<span class="se17">def</span><span class="se2"> </span><span class="se28">_brenner</span><span class="se23">(</span><span class="se55">im</span><span class="se23">,</span><span class="se2"> </span><span class="se55">direction</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se55">direction</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se58">'h'</span><span class="se23">:</span>
<span class="se2"> </span><span class="se55">xo</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">2</span>
<span class="se2"> </span><span class="se55">yo</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">0</span>
<span class="se2"> </span><span class="se17">elif</span><span class="se2"> </span><span class="se55">direction</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se58">'v'</span><span class="se23">:</span>
<span class="se2"> </span><span class="se55">xo</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">0</span>
<span class="se2"> </span><span class="se55">yo</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">2</span>
<span class="se2"> </span><span class="se17">else</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">raise</span><span class="se2"> </span><span class="se24">ValueError</span><span class="se23">(</span><span class="se58">'direction must be h or v.'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">iml</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">numpy</span><span class="se23">.</span><span class="se28">pad</span><span class="se23">(</span><span class="se55">im</span><span class="se23">[</span><span class="se19">0</span><span class="se23">:</span><span class="se55">im</span><span class="se23">.</span><span class="se55">shape</span><span class="se23">[</span><span class="se19">0</span><span class="se23">]</span><span class="se25">-</span><span class="se55">yo</span><span class="se23">,</span><span class="se2"> </span><span class="se19">0</span><span class="se23">:</span><span class="se55">im</span><span class="se23">.</span><span class="se55">shape</span><span class="se23">[</span><span class="se19">1</span><span class="se23">]</span><span class="se25">-</span><span class="se55">xo</span><span class="se23">],</span><span class="se2"> </span><span class="se23">((</span><span class="se55">yo</span><span class="se23">,</span><span class="se2"> </span><span class="se19">0</span><span class="se23">),</span><span class="se2"> </span><span class="se23">(</span><span class="se55">xo</span><span class="se23">,</span><span class="se2"> </span><span class="se19">0</span><span class="se23">)),</span><span class="se2"> </span><span class="se55">mode</span><span class="se23">=</span><span class="se58">'constant'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">imr</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">im</span><span class="se23">.</span><span class="se28">copy</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se55">direction</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se58">'h'</span><span class="se23">:</span>
<span class="se2"> </span><span class="se55">imr</span><span class="se23">[:,</span><span class="se2"> </span><span class="se23">:</span><span class="se55">xo</span><span class="se23">]</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">0</span>
<span class="se2"> </span><span class="se17">else</span><span class="se23">:</span>
<span class="se2"> </span><span class="se55">imr</span><span class="se23">[:</span><span class="se55">yo</span><span class="se23">,</span><span class="se2"> </span><span class="se23">:]</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se19">0</span>
<span class="se2"> </span><span class="se17">return</span><span class="se2"> </span><span class="se55">iml</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se55">imr</span>
<span class="se17">def</span><span class="se2"> </span><span class="se28">brennerFocusMeasure</span><span class="se23">(</span><span class="se55">im</span><span class="se23">):</span>
<span class="se2"> </span><span class="se55">imh</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se28">_brenner</span><span class="se23">(</span><span class="se55">im</span><span class="se23">,</span><span class="se2"> </span><span class="se58">'h'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">imv</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se28">_brenner</span><span class="se23">(</span><span class="se55">im</span><span class="se23">,</span><span class="se2"> </span><span class="se58">'v'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">return</span><span class="se2"> </span><span class="se55">numpy</span><span class="se23">.</span><span class="se28">sqrt</span><span class="se23">(</span><span class="se55">imh</span><span class="se25">**</span><span class="se19">2</span><span class="se2"> </span><span class="se25">+</span><span class="se2"> </span><span class="se55">imv</span><span class="se25">**</span><span class="se19">2</span><span class="se23">)</span>
<span class="se17">class</span><span class="se2"> </span><span class="se55">LinearSearchAutofocuser</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">def</span><span class="se2"> </span><span class="se24">__init__</span><span class="se23">(</span><span class="se17">self</span><span class="se23">,</span><span class="se2"> </span><span class="se55">camera</span><span class="se23">,</span><span class="se2"> </span><span class="se55">zDrive</span><span class="se23">,</span><span class="se2"> </span><span class="se55">minZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">maxZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">stepsPerRound</span><span class="se23">,</span><span class="se2"> </span><span class="se55">numberOfRounds</span><span class="se23">,</span><span class="se2"> </span><span class="se55">focusMeasure</span><span class="se23">=</span><span class="se55">brennerFocusMeasure</span><span class="se23">,</span><span class="se2"> </span><span class="se55">rw</span><span class="se23">=</span><span class="se24">None</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">False</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">camera</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">zDrive</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zRange</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">(</span><span class="se55">minZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">maxZ</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_stepsPerRound</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">stepsPerRound</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_numberOfRounds</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">numberOfRounds</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_focusMeasure</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">focusMeasure</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_rw</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">rw</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">idleGt</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">greenlet</span><span class="se23">.</span><span class="se28">getcurrent</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">runGt</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">greenlet</span><span class="se23">.</span><span class="se28">greenlet</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_run</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">bestZ</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">None</span>
<span class="se2"> </span><span class="se17">def</span><span class="se2"> </span><span class="se28">abort</span><span class="se23">(</span><span class="se17">self</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">runGt</span><span class="se23">.</span><span class="se28">switch</span><span class="se23">(</span><span class="se24">False</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">def</span><span class="se2"> </span><span class="se28">_run</span><span class="se23">(</span><span class="se17">self</span><span class="se23">):</span>
<span class="se2"> </span><span class="se55">t0</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">time</span><span class="se23">.</span><span class="se28">time</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">bestZ</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">None</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">posChanged</span><span class="se23">.</span><span class="se28">connect</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrivePosChanged</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">True</span>
<span class="se2"> </span><span class="se55">curZRange</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zRange</span>
<span class="se2"> </span><span class="se55">buffers</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">[</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">makeAcquisitionBuffer</span><span class="se23">()</span><span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">i</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se24">range</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_stepsPerRound</span><span class="se23">)]</span>
<span class="se2"> </span>
<span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">roundIdx</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se24">range</span><span class="se23">(</span><span class="se19">0</span><span class="se23">,</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_numberOfRounds</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'Starting autofocus round {}.'</span><span class="se23">.</span><span class="se28">format</span><span class="se23">(</span><span class="se55">roundIdx</span><span class="se23">))</span>
<span class="se2"> </span><span class="se55">fmvs</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">[]</span>
<span class="se2"> </span><span class="se55">stepIdxsDone</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">[]</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se55">roundIdx</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se19">0</span><span class="se23">:</span>
<span class="se2"> </span><span class="se49"># The first round computes focus measures for every step in the Z range, including endpoints</span>
<span class="se2"> </span><span class="se55">steps</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">numpy</span><span class="se23">.</span><span class="se28">linspace</span><span class="se23">(</span><span class="se25">*</span><span class="se55">curZRange</span><span class="se23">,</span><span class="se2"> </span><span class="se55">num</span><span class="se23">=</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_stepsPerRound</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">else</span><span class="se23">:</span>
<span class="se2"> </span><span class="se49"># Every subsequent round's Z range is the interval between the previous round's Z steps bracketing the Z step</span>
<span class="se2"> </span><span class="se49"># with the highest focus measure value:</span>
<span class="se2"> </span><span class="se49">#</span>
<span class="se2"> </span><span class="se49"># ----- Previous Z step above best previous Z</span>
<span class="se2"> </span><span class="se49"># | --- Current Z step</span>
<span class="se2"> </span><span class="se49"># | --- "</span>
<span class="se2"> </span><span class="se49"># | --- "</span>
<span class="se2"> </span><span class="se49"># ----- Previous Z step with best focus measure value</span>
<span class="se2"> </span><span class="se49"># | --- Current Z step</span>
<span class="se2"> </span><span class="se49"># | --- "</span>
<span class="se2"> </span><span class="se49"># | --- "</span>
<span class="se2"> </span><span class="se49"># ----- Previous Z step below best previous Z</span>
<span class="se2"> </span><span class="se49">#</span>
<span class="se2"> </span><span class="se49"># So, if a subsequent round's step sequence is computed in the same manner as the first round's step sequence,</span>
<span class="se2"> </span><span class="se49"># it will include the previous round's bracketing Z step positions as endpoints, repeating the focus measure</span>
<span class="se2"> </span><span class="se49"># computation for those positions, increasing the computational expense of the linear search. This is most clearly</span>
<span class="se2"> </span><span class="se49"># illustrated by the case where stepsPerRound is 3 and first round best Z step is the middle position: in this case,</span>
<span class="se2"> </span><span class="se49"># the linear search will repeat the same calculations at the same Z step positions for an arbitrary number of rounds,</span>
<span class="se2"> </span><span class="se49"># failing to refine the best Z step position.</span>
<span class="se2"> </span><span class="se49">#</span>
<span class="se2"> </span><span class="se49"># This is avoided while maintaining uniform step size by treating subsequent Z ranges as an open interval bounded</span>
<span class="se2"> </span><span class="se49"># by bracketing Z step positions. If stepsPerRound is odd, the best previous Z step position focus measure is</span>
<span class="se2"> </span><span class="se49"># still recomputed, but this is considered acceptable.</span>
<span class="se2"> </span><span class="se55">steps</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">numpy</span><span class="se23">.</span><span class="se28">linspace</span><span class="se23">(</span><span class="se25">*</span><span class="se55">curZRange</span><span class="se23">,</span><span class="se2"> </span><span class="se55">num</span><span class="se23">=</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_stepsPerRound</span><span class="se25">+</span><span class="se19">2</span><span class="se23">)[</span><span class="se19">1</span><span class="se23">:</span><span class="se25">-</span><span class="se19">1</span><span class="se23">]</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_Flush</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">shutter</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">Shutter</span><span class="se23">.</span><span class="se55">Rolling</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">triggerMode</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">TriggerMode</span><span class="se23">.</span><span class="se55">Software</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">cycleMode</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">CycleMode</span><span class="se23">.</span><span class="se55">Fixed</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">frameCount</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_stepsPerRound</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">frameCount</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">buffer</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se55">buffers</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_QueueBuffer</span><span class="se23">(</span><span class="se55">buffer</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_Command</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">Feature</span><span class="se23">.</span><span class="se55">AcquisitionStart</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">stepIdx</span><span class="se23">,</span><span class="se2"> </span><span class="se55">z</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se28">enumerate</span><span class="se23">(</span><span class="se55">steps</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">pos</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">z</span>
<span class="se2"> </span><span class="se49"># Return to main event loop (or whatever was the enclosing greenlet when this class was instantiated) until</span>
<span class="se2"> </span><span class="se49"># the stage stops moving, aborting and cleaning up if resumed with switch(False)</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se17">not</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">idleGt</span><span class="se23">.</span><span class="se28">switch</span><span class="se23">():</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'Autofocus aborted.'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_Command</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">Feature</span><span class="se23">.</span><span class="se55">AcquisitionStop</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_Flush</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">False</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">posChanged</span><span class="se23">.</span><span class="se28">disconnect</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrivePosChanged</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">raise</span><span class="se2"> </span><span class="se55">greenlet</span><span class="se23">.</span><span class="se28">GreenletExit</span><span class="se23">()</span>
<span class="se2"> </span><span class="se49"># Resuming after stage has moved</span>
<span class="se2"> </span><span class="se55">actualZ</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">pos</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se24">abs</span><span class="se23">(</span><span class="se55">actualZ</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se55">z</span><span class="se23">)</span><span class="se2"> </span><span class="se25">></span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">_factor</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se24">sys</span><span class="se23">.</span><span class="se55">float_info</span><span class="se23">.</span><span class="se55">epsilon</span><span class="se23">:</span>
<span class="se2"> </span><span class="se55">w</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se58">'Current Z position ({0}) does not match requested Z position ({1}). '</span>
<span class="se2"> </span><span class="se55">w</span><span class="se25">+</span><span class="se23">=</span><span class="se2"> </span><span class="se58">'The autofocus step for {1} is being skipped. This can occur if the requested Z position '</span>
<span class="se2"> </span><span class="se55">w</span><span class="se25">+</span><span class="se23">=</span><span class="se2"> </span><span class="se58">'is out of range or if the scope\'s Z position controller has been moved during the '</span>
<span class="se2"> </span><span class="se55">w</span><span class="se25">+</span><span class="se23">=</span><span class="se2"> </span><span class="se58">'auto-focus operation.'</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se55">w</span><span class="se23">.</span><span class="se28">format</span><span class="se23">(</span><span class="se55">actualZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">z</span><span class="se23">))</span>
<span class="se2"> </span><span class="se17">continue</span>
<span class="se2"> </span><span class="se49"># Stage Z position is actually what we requested. Command exposure.</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">commandSoftwareTrigger</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'exposed '</span><span class="se23">,</span><span class="se2"> </span><span class="se55">stepIdx</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">stepIdxsDone</span><span class="se23">.</span><span class="se24">append</span><span class="se23">(</span><span class="se55">stepIdx</span><span class="se23">)</span>
<span class="se2"> </span><span class="se49"># Retrieve, show, and process resulting exposures</span>
<span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">bufferIdx</span><span class="se23">,</span><span class="se2"> </span><span class="se55">stepIdx</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se28">enumerate</span><span class="se23">(</span><span class="se55">stepIdxsDone</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_WaitBuffer</span><span class="se23">(</span><span class="se19">1000</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'got buffer'</span><span class="se23">,</span><span class="se2"> </span><span class="se55">bufferIdx</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">buffer</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">buffers</span><span class="se23">[</span><span class="se55">bufferIdx</span><span class="se23">]</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_rw</span><span class="se2"> </span><span class="se17">is</span><span class="se2"> </span><span class="se17">not</span><span class="se2"> </span><span class="se24">None</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_rw</span><span class="se23">.</span><span class="se28">showImage</span><span class="se23">(</span><span class="se55">buffer</span><span class="se23">)</span>
<span class="se2"> </span><span class="se55">im</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">buffer</span><span class="se23">.</span><span class="se28">astype</span><span class="se23">(</span><span class="se55">numpy</span><span class="se23">.</span><span class="se55">float32</span><span class="se23">)</span><span class="se2"> </span><span class="se25">/</span><span class="se2"> </span><span class="se19">65535</span>
<span class="se2"> </span><span class="se55">fmv</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se28">_focusMeasure</span><span class="se23">(</span><span class="se55">im</span><span class="se23">)</span><span class="se25">**</span><span class="se19">2</span><span class="se23">).</span><span class="se28">sum</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'round={:02}, z={:<10}, focus_measure={}'</span><span class="se23">.</span><span class="se28">format</span><span class="se23">(</span><span class="se55">roundIdx</span><span class="se23">,</span><span class="se2"> </span><span class="se55">steps</span><span class="se23">[</span><span class="se55">stepIdx</span><span class="se23">],</span><span class="se2"> </span><span class="se55">fmv</span><span class="se23">))</span>
<span class="se2"> </span><span class="se55">fmvs</span><span class="se23">.</span><span class="se24">append</span><span class="se23">((</span><span class="se55">steps</span><span class="se23">[</span><span class="se55">stepIdx</span><span class="se23">],</span><span class="se2"> </span><span class="se55">fmv</span><span class="se23">))</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se28">AT_Command</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">_camera</span><span class="se23">.</span><span class="se55">Feature</span><span class="se23">.</span><span class="se55">AcquisitionStop</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se24">len</span><span class="se23">(</span><span class="se55">fmvs</span><span class="se23">)</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se19">0</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'Failed to move to any of the Z step positions.'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">False</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">posChanged</span><span class="se23">.</span><span class="se28">disconnect</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrivePosChanged</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">raise</span><span class="se2"> </span><span class="se55">greenlet</span><span class="se23">.</span><span class="se28">GreenletExit</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se24">len</span><span class="se23">(</span><span class="se55">fmvs</span><span class="se23">)</span><span class="se2"> </span><span class="se25">==</span><span class="se2"> </span><span class="se19">1</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'Successfully moved to only one of the Z step positions, making that position the best found.'</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">bestZ</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">fmvs</span><span class="se23">[</span><span class="se19">0</span><span class="se23">][</span><span class="se19">0</span><span class="se23">]</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">False</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">posChanged</span><span class="se23">.</span><span class="se28">disconnect</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrivePosChanged</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">raise</span><span class="se2"> </span><span class="se55">greenlet</span><span class="se23">.</span><span class="se28">GreenletExit</span><span class="se23">()</span>
<span class="se2"> </span><span class="se55">bestZIdx</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">numpy</span><span class="se23">.</span><span class="se28">array</span><span class="se23">([</span><span class="se55">fmv</span><span class="se23">[</span><span class="se19">1</span><span class="se23">]</span><span class="se2"> </span><span class="se17">for</span><span class="se2"> </span><span class="se55">fmv</span><span class="se2"> </span><span class="se17">in</span><span class="se2"> </span><span class="se55">fmvs</span><span class="se23">],</span><span class="se2"> </span><span class="se55">dtype</span><span class="se23">=</span><span class="se55">numpy</span><span class="se23">.</span><span class="se55">float64</span><span class="se23">).</span><span class="se28">argmax</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se55">roundIdx</span><span class="se2"> </span><span class="se25">+</span><span class="se2"> </span><span class="se19">1</span><span class="se2"> </span><span class="se25"><</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_numberOfRounds</span><span class="se23">:</span>
<span class="se2"> </span><span class="se49"># Next round, search the range between the steps adjacent to the best step</span>
<span class="se2"> </span><span class="se55">curZRange</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se23">(</span><span class="se2"> </span><span class="se55">steps</span><span class="se23">[</span><span class="se24">max</span><span class="se23">(</span><span class="se55">bestZIdx</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se19">1</span><span class="se23">,</span><span class="se2"> </span><span class="se19">0</span><span class="se23">)],</span>
<span class="se2"> </span><span class="se55">steps</span><span class="se23">[</span><span class="se24">min</span><span class="se23">(</span><span class="se55">bestZIdx</span><span class="se2"> </span><span class="se25">+</span><span class="se2"> </span><span class="se19">1</span><span class="se23">,</span><span class="se2"> </span><span class="se24">len</span><span class="se23">(</span><span class="se55">fmvs</span><span class="se23">)</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se19">1</span><span class="se23">)]</span><span class="se2"> </span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">else</span><span class="se23">:</span>
<span class="se2"> </span><span class="se49"># There is no next round. Store result.</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">bestZ</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se55">steps</span><span class="se23">[</span><span class="se55">bestZIdx</span><span class="se23">]</span>
<span class="se2"> </span><span class="se17">print</span><span class="se23">(</span><span class="se58">'Autofocus completed ({}s).'</span><span class="se23">.</span><span class="se28">format</span><span class="se23">(</span><span class="se55">time</span><span class="se23">.</span><span class="se28">time</span><span class="se23">()</span><span class="se2"> </span><span class="se25">-</span><span class="se2"> </span><span class="se55">t0</span><span class="se23">))</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se24">False</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">posChanged</span><span class="se23">.</span><span class="se28">disconnect</span><span class="se23">(</span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrivePosChanged</span><span class="se23">)</span>
<span class="se2"> </span><span class="se17">def</span><span class="se2"> </span><span class="se28">_zDrivePosChanged</span><span class="se23">(</span><span class="se17">self</span><span class="se23">,</span><span class="se2"> </span><span class="se17">_</span><span class="se23">):</span>
<span class="se2"> </span><span class="se17">if</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_running</span><span class="se2"> </span><span class="se17">and</span><span class="se2"> </span><span class="se17">not</span><span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">_zDrive</span><span class="se23">.</span><span class="se55">moving</span><span class="se23">:</span>
<span class="se2"> </span><span class="se17">self</span><span class="se23">.</span><span class="se55">runGt</span><span class="se23">.</span><span class="se28">switch</span><span class="se23">(</span><span class="se24">True</span><span class="se23">)</span>
<span class="se17">def</span><span class="se2"> </span><span class="se28">linearSearchAutofocus</span><span class="se23">(</span><span class="se55">camera</span><span class="se23">,</span><span class="se2"> </span><span class="se55">zDrive</span><span class="se23">,</span><span class="se2"> </span><span class="se55">minZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">maxZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">stepsPerRound</span><span class="se23">,</span><span class="se2"> </span><span class="se55">numberOfRounds</span><span class="se23">,</span><span class="se2"> </span><span class="se55">focusMeasure</span><span class="se23">=</span><span class="se55">brennerFocusMeasure</span><span class="se23">,</span><span class="se2"> </span><span class="se55">rw</span><span class="se23">=</span><span class="se24">None</span><span class="se23">):</span>
<span class="se2"> </span><span class="se55">autofocuser</span><span class="se2"> </span><span class="se23">=</span><span class="se2"> </span><span class="se28">_Autofocuser</span><span class="se23">(</span><span class="se55">camera</span><span class="se23">,</span><span class="se2"> </span><span class="se55">zDrive</span><span class="se23">,</span><span class="se2"> </span><span class="se55">minZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">maxZ</span><span class="se23">,</span><span class="se2"> </span><span class="se55">stepsPerRound</span><span class="se23">,</span><span class="se2"> </span><span class="se55">numberOfRounds</span><span class="se23">,</span><span class="se2"> </span><span class="se55">rw</span><span class="se23">)</span>
<span class="se2"> </span><span class="se49"># greenlet.run(..) blocks until the greenlet is dead and is the correct call to use when blocking behavior is desired</span>
<span class="se2"> </span><span class="se55">autofocuser</span><span class="se23">.</span><span class="se55">runGt</span><span class="se23">.</span><span class="se28">run</span><span class="se23">()</span>
<span class="se2"> </span><span class="se17">return</span><span class="se2"> </span><span class="se55">autofocuser</span><span class="se23">.</span><span class="se55">bestZ</span>
</pre>
</div>
Erik Hvatumhttp://www.blogger.com/profile/13886932405360697019noreply@blogger.com0