| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567 |
- /*
- * Copyright © 2011 Red Hat All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
- * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- */
- /*
- * Authors:
- * Jérôme Glisse <jglisse@redhat.com>
- */
- #include <stdbool.h>
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include "drm.h"
- #include "libdrm_macros.h"
- #include "xf86drm.h"
- #include "radeon_drm.h"
- #include "radeon_surface.h"
- #define CIK_TILE_MODE_COLOR_2D 14
- #define CIK_TILE_MODE_COLOR_2D_SCANOUT 10
- #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64 0
- #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128 1
- #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256 2
- #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512 3
- #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4
- #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
- #define MAX2(A, B) ((A) > (B) ? (A) : (B))
- #define MIN2(A, B) ((A) < (B) ? (A) : (B))
- /* keep this private */
- enum radeon_family {
- CHIP_UNKNOWN,
- CHIP_R600,
- CHIP_RV610,
- CHIP_RV630,
- CHIP_RV670,
- CHIP_RV620,
- CHIP_RV635,
- CHIP_RS780,
- CHIP_RS880,
- CHIP_RV770,
- CHIP_RV730,
- CHIP_RV710,
- CHIP_RV740,
- CHIP_CEDAR,
- CHIP_REDWOOD,
- CHIP_JUNIPER,
- CHIP_CYPRESS,
- CHIP_HEMLOCK,
- CHIP_PALM,
- CHIP_SUMO,
- CHIP_SUMO2,
- CHIP_BARTS,
- CHIP_TURKS,
- CHIP_CAICOS,
- CHIP_CAYMAN,
- CHIP_ARUBA,
- CHIP_TAHITI,
- CHIP_PITCAIRN,
- CHIP_VERDE,
- CHIP_OLAND,
- CHIP_HAINAN,
- CHIP_BONAIRE,
- CHIP_KAVERI,
- CHIP_KABINI,
- CHIP_HAWAII,
- CHIP_MULLINS,
- CHIP_LAST,
- };
- typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf);
- typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf);
- struct radeon_hw_info {
- /* apply to r6, eg */
- uint32_t group_bytes;
- uint32_t num_banks;
- uint32_t num_pipes;
- /* apply to eg */
- uint32_t row_size;
- unsigned allow_2d;
- /* apply to si */
- uint32_t tile_mode_array[32];
- /* apply to cik */
- uint32_t macrotile_mode_array[16];
- };
- struct radeon_surface_manager {
- int fd;
- uint32_t device_id;
- struct radeon_hw_info hw_info;
- unsigned family;
- hw_init_surface_t surface_init;
- hw_best_surface_t surface_best;
- };
- /* helper */
- static int radeon_get_value(int fd, unsigned req, uint32_t *value)
- {
- struct drm_radeon_info info = {};
- int r;
- *value = 0;
- info.request = req;
- info.value = (uintptr_t)value;
- r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
- sizeof(struct drm_radeon_info));
- return r;
- }
- static int radeon_get_family(struct radeon_surface_manager *surf_man)
- {
- switch (surf_man->device_id) {
- #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
- #include "r600_pci_ids.h"
- #undef CHIPSET
- default:
- return -EINVAL;
- }
- return 0;
- }
- static unsigned next_power_of_two(unsigned x)
- {
- if (x <= 1)
- return 1;
- return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
- }
- static unsigned mip_minify(unsigned size, unsigned level)
- {
- unsigned val;
- val = MAX2(1, size >> level);
- if (level > 0)
- val = next_power_of_two(val);
- return val;
- }
- static void surf_minify(struct radeon_surface *surf,
- struct radeon_surface_level *surflevel,
- unsigned bpe, unsigned level,
- uint32_t xalign, uint32_t yalign, uint32_t zalign,
- uint64_t offset)
- {
- surflevel->npix_x = mip_minify(surf->npix_x, level);
- surflevel->npix_y = mip_minify(surf->npix_y, level);
- surflevel->npix_z = mip_minify(surf->npix_z, level);
- surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
- if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
- !(surf->flags & RADEON_SURF_FMASK)) {
- if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
- surflevel->mode = RADEON_SURF_MODE_1D;
- return;
- }
- }
- surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
- surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
- surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
- surflevel->offset = offset;
- surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
- surflevel->slice_size = (uint64_t)surflevel->pitch_bytes * surflevel->nblk_y;
- surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
- }
- /* ===========================================================================
- * r600/r700 family
- */
- static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
- {
- uint32_t tiling_config;
- drmVersionPtr version;
- int r;
- r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
- &tiling_config);
- if (r) {
- return r;
- }
- surf_man->hw_info.allow_2d = 0;
- version = drmGetVersion(surf_man->fd);
- if (version && version->version_minor >= 14) {
- surf_man->hw_info.allow_2d = 1;
- }
- drmFreeVersion(version);
- switch ((tiling_config & 0xe) >> 1) {
- case 0:
- surf_man->hw_info.num_pipes = 1;
- break;
- case 1:
- surf_man->hw_info.num_pipes = 2;
- break;
- case 2:
- surf_man->hw_info.num_pipes = 4;
- break;
- case 3:
- surf_man->hw_info.num_pipes = 8;
- break;
- default:
- surf_man->hw_info.num_pipes = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0x30) >> 4) {
- case 0:
- surf_man->hw_info.num_banks = 4;
- break;
- case 1:
- surf_man->hw_info.num_banks = 8;
- break;
- default:
- surf_man->hw_info.num_banks = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xc0) >> 6) {
- case 0:
- surf_man->hw_info.group_bytes = 256;
- break;
- case 1:
- surf_man->hw_info.group_bytes = 512;
- break;
- default:
- surf_man->hw_info.group_bytes = 256;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- return 0;
- }
- static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign;
- unsigned i;
- /* compute alignment */
- if (!start_level) {
- surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
- }
- /* the 32 alignment is for scanout, cb or db but to allow texture to be
- * easily bound as such we force this alignment to all surface
- */
- xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
- yalign = 1;
- zalign = 1;
- if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
- surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign;
- unsigned i;
- /* compute alignment */
- if (!start_level) {
- surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
- }
- xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
- yalign = 1;
- zalign = 1;
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
- surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign, tilew;
- unsigned i;
- /* compute alignment */
- tilew = 8;
- xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
- xalign = MAX2(tilew, xalign);
- yalign = tilew;
- zalign = 1;
- if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
- }
- if (!start_level) {
- surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_1D;
- surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign, tilew;
- unsigned i;
- /* compute alignment */
- tilew = 8;
- zalign = 1;
- xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
- (tilew * surf->bpe * surf->nsamples);
- xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
- if (surf->flags & RADEON_SURF_FMASK)
- xalign = MAX2(128, xalign);
- yalign = tilew * surf_man->hw_info.num_pipes;
- if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
- }
- if (!start_level) {
- surf->bo_alignment =
- MAX2(surf_man->hw_info.num_pipes *
- surf_man->hw_info.num_banks *
- surf->nsamples * surf->bpe * 64,
- xalign * yalign * surf->nsamples * surf->bpe);
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_2D;
- surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
- if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
- return r6_surface_init_1d(surf_man, surf, offset, i);
- }
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int r6_surface_init(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode;
- int r;
- /* MSAA surfaces support the 2D mode only. */
- if (surf->nsamples > 1) {
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
- /* zbuffer only support 1D or 2D tiled surface */
- switch (mode) {
- case RADEON_SURF_MODE_1D:
- case RADEON_SURF_MODE_2D:
- break;
- default:
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- break;
- }
- }
- /* force 1d on kernel that can't do 2d */
- if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
- if (surf->nsamples > 1) {
- fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
- return -EFAULT;
- }
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(mode, MODE);
- }
- /* check surface dimension */
- if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
- return -EINVAL;
- }
- /* check mipmap last_level */
- if (surf->last_level > 14) {
- return -EINVAL;
- }
- /* check tiling mode */
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR:
- r = r6_surface_init_linear(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_1D:
- r = r6_surface_init_1d(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_2D:
- r = r6_surface_init_2d(surf_man, surf, 0, 0);
- break;
- default:
- return -EINVAL;
- }
- return r;
- }
- static int r6_surface_best(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- /* no value to optimize for r6xx/r7xx */
- return 0;
- }
- /* ===========================================================================
- * evergreen family
- */
- static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
- {
- uint32_t tiling_config;
- drmVersionPtr version;
- int r;
- r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
- &tiling_config);
- if (r) {
- return r;
- }
- surf_man->hw_info.allow_2d = 0;
- version = drmGetVersion(surf_man->fd);
- if (version && version->version_minor >= 16) {
- surf_man->hw_info.allow_2d = 1;
- }
- drmFreeVersion(version);
- switch (tiling_config & 0xf) {
- case 0:
- surf_man->hw_info.num_pipes = 1;
- break;
- case 1:
- surf_man->hw_info.num_pipes = 2;
- break;
- case 2:
- surf_man->hw_info.num_pipes = 4;
- break;
- case 3:
- surf_man->hw_info.num_pipes = 8;
- break;
- default:
- surf_man->hw_info.num_pipes = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf0) >> 4) {
- case 0:
- surf_man->hw_info.num_banks = 4;
- break;
- case 1:
- surf_man->hw_info.num_banks = 8;
- break;
- case 2:
- surf_man->hw_info.num_banks = 16;
- break;
- default:
- surf_man->hw_info.num_banks = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf00) >> 8) {
- case 0:
- surf_man->hw_info.group_bytes = 256;
- break;
- case 1:
- surf_man->hw_info.group_bytes = 512;
- break;
- default:
- surf_man->hw_info.group_bytes = 256;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf000) >> 12) {
- case 0:
- surf_man->hw_info.row_size = 1024;
- break;
- case 1:
- surf_man->hw_info.row_size = 2048;
- break;
- case 2:
- surf_man->hw_info.row_size = 4096;
- break;
- default:
- surf_man->hw_info.row_size = 4096;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- return 0;
- }
- static void eg_surf_minify(struct radeon_surface *surf,
- struct radeon_surface_level *surflevel,
- unsigned bpe,
- unsigned level,
- unsigned slice_pt,
- unsigned mtilew,
- unsigned mtileh,
- unsigned mtileb,
- uint64_t offset)
- {
- unsigned mtile_pr, mtile_ps;
- surflevel->npix_x = mip_minify(surf->npix_x, level);
- surflevel->npix_y = mip_minify(surf->npix_y, level);
- surflevel->npix_z = mip_minify(surf->npix_z, level);
- surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
- if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
- !(surf->flags & RADEON_SURF_FMASK)) {
- if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
- surflevel->mode = RADEON_SURF_MODE_1D;
- return;
- }
- }
- surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
- surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
- surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
- /* macro tile per row */
- mtile_pr = surflevel->nblk_x / mtilew;
- /* macro tile per slice */
- mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
- surflevel->offset = offset;
- surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
- surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
- surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
- }
- static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- struct radeon_surface_level *level,
- unsigned bpe,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign, tilew;
- unsigned i;
- /* compute alignment */
- tilew = 8;
- xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
- xalign = MAX2(tilew, xalign);
- yalign = tilew;
- zalign = 1;
- if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
- }
- if (!start_level) {
- unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
- surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
- if (offset) {
- offset = ALIGN(offset, alignment);
- }
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- level[i].mode = RADEON_SURF_MODE_1D;
- surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- struct radeon_surface_level *level,
- unsigned bpe, unsigned tile_split,
- uint64_t offset, unsigned start_level)
- {
- unsigned tilew, tileh, tileb;
- unsigned mtilew, mtileh, mtileb;
- unsigned slice_pt;
- unsigned i;
- /* compute tile values */
- tilew = 8;
- tileh = 8;
- tileb = tilew * tileh * bpe * surf->nsamples;
- /* slices per tile */
- slice_pt = 1;
- if (tileb > tile_split && tile_split) {
- slice_pt = tileb / tile_split;
- }
- tileb = tileb / slice_pt;
- /* macro tile width & height */
- mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
- mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
- /* macro tile bytes */
- mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
- if (!start_level) {
- unsigned alignment = MAX2(256, mtileb);
- surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
- if (offset) {
- offset = ALIGN(offset, alignment);
- }
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- level[i].mode = RADEON_SURF_MODE_2D;
- eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
- if (level[i].mode == RADEON_SURF_MODE_1D) {
- return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
- }
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- }
- return 0;
- }
- static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned mode)
- {
- unsigned tileb;
- /* check surface dimension */
- if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
- return -EINVAL;
- }
- /* check mipmap last_level */
- if (surf->last_level > 15) {
- return -EINVAL;
- }
- /* force 1d on kernel that can't do 2d */
- if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
- if (surf->nsamples > 1) {
- fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
- return -EFAULT;
- }
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(mode, MODE);
- }
- /* check tile split */
- if (mode == RADEON_SURF_MODE_2D) {
- switch (surf->tile_split) {
- case 64:
- case 128:
- case 256:
- case 512:
- case 1024:
- case 2048:
- case 4096:
- break;
- default:
- return -EINVAL;
- }
- switch (surf->mtilea) {
- case 1:
- case 2:
- case 4:
- case 8:
- break;
- default:
- return -EINVAL;
- }
- /* check aspect ratio */
- if (surf_man->hw_info.num_banks < surf->mtilea) {
- return -EINVAL;
- }
- /* check bank width */
- switch (surf->bankw) {
- case 1:
- case 2:
- case 4:
- case 8:
- break;
- default:
- return -EINVAL;
- }
- /* check bank height */
- switch (surf->bankh) {
- case 1:
- case 2:
- case 4:
- case 8:
- break;
- default:
- return -EINVAL;
- }
- tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
- if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
- return -EINVAL;
- }
- }
- return 0;
- }
- static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
- int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
- /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
- struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
- struct radeon_surface_level *stencil_level =
- (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
- r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
- if (r)
- return r;
- if (is_depth_stencil) {
- r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
- surf->bo_size, 0);
- surf->stencil_offset = stencil_level[0].offset;
- }
- return r;
- }
- static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
- int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
- /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
- struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
- struct radeon_surface_level *stencil_level =
- (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
- r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
- surf->tile_split, 0, 0);
- if (r)
- return r;
- if (is_depth_stencil) {
- r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
- surf->stencil_tile_split, surf->bo_size, 0);
- surf->stencil_offset = stencil_level[0].offset;
- }
- return r;
- }
- static int eg_surface_init(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode;
- int r;
- /* MSAA surfaces support the 2D mode only. */
- if (surf->nsamples > 1) {
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
- /* zbuffer only support 1D or 2D tiled surface */
- switch (mode) {
- case RADEON_SURF_MODE_1D:
- case RADEON_SURF_MODE_2D:
- break;
- default:
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- break;
- }
- }
- r = eg_surface_sanity(surf_man, surf, mode);
- if (r) {
- return r;
- }
- surf->stencil_offset = 0;
- surf->bo_alignment = 0;
- /* check tiling mode */
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR:
- r = r6_surface_init_linear(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_1D:
- r = eg_surface_init_1d_miptrees(surf_man, surf);
- break;
- case RADEON_SURF_MODE_2D:
- r = eg_surface_init_2d_miptrees(surf_man, surf);
- break;
- default:
- return -EINVAL;
- }
- return r;
- }
- static unsigned log2_int(unsigned x)
- {
- unsigned l;
- if (x < 2) {
- return 0;
- }
- for (l = 2; ; l++) {
- if ((unsigned)(1 << l) > x) {
- return l - 1;
- }
- }
- return 0;
- }
- /* compute best tile_split, bankw, bankh, mtilea
- * depending on surface
- */
- static int eg_surface_best(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, tileb, h_over_w;
- int r;
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- /* set some default value to avoid sanity check choking on them */
- surf->tile_split = 1024;
- surf->bankw = 1;
- surf->bankh = 1;
- surf->mtilea = surf_man->hw_info.num_banks;
- tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
- for (; surf->bankh <= 8; surf->bankh *= 2) {
- if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
- break;
- }
- }
- if (surf->mtilea > 8) {
- surf->mtilea = 8;
- }
- r = eg_surface_sanity(surf_man, surf, mode);
- if (r) {
- return r;
- }
- if (mode != RADEON_SURF_MODE_2D) {
- /* nothing to do for non 2D tiled surface */
- return 0;
- }
- /* Tweak TILE_SPLIT for performance here. */
- if (surf->nsamples > 1) {
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
- switch (surf->nsamples) {
- case 2:
- surf->tile_split = 128;
- break;
- case 4:
- surf->tile_split = 128;
- break;
- case 8:
- surf->tile_split = 256;
- break;
- case 16: /* cayman only */
- surf->tile_split = 512;
- break;
- default:
- fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
- surf->nsamples, __LINE__);
- return -EINVAL;
- }
- surf->stencil_tile_split = 64;
- } else {
- /* tile split must be >= 256 for colorbuffer surfaces,
- * SAMPLE_SPLIT = tile_split / (bpe * 64), the optimal value is 2
- */
- surf->tile_split = MAX2(2 * surf->bpe * 64, 256);
- if (surf->tile_split > 4096)
- surf->tile_split = 4096;
- }
- } else {
- /* set tile split to row size */
- surf->tile_split = surf_man->hw_info.row_size;
- surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
- }
- /* bankw or bankh greater than 1 increase alignment requirement, not
- * sure if it's worth using smaller bankw & bankh to stick with 2D
- * tiling on small surface rather than falling back to 1D tiling.
- * Use recommended value based on tile size for now.
- *
- * fmask buffer has different optimal value figure them out once we
- * use it.
- */
- if (surf->flags & RADEON_SURF_SBUFFER) {
- /* assume 1 bytes for stencil, we optimize for stencil as stencil
- * and depth shares surface values
- */
- tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
- } else {
- tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
- }
- /* use bankw of 1 to minimize width alignment, might be interesting to
- * increase it for large surface
- */
- surf->bankw = 1;
- switch (tileb) {
- case 64:
- surf->bankh = 4;
- break;
- case 128:
- case 256:
- surf->bankh = 2;
- break;
- default:
- surf->bankh = 1;
- break;
- }
- /* double check the constraint */
- for (; surf->bankh <= 8; surf->bankh *= 2) {
- if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
- break;
- }
- }
- h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
- (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
- surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
- return 0;
- }
- /* ===========================================================================
- * Southern Islands family
- */
- #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
- #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
- #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
- #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
- #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
- #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
- #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
- #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
- #define SI__TILE_SPLIT__64B 0
- #define SI__TILE_SPLIT__128B 1
- #define SI__TILE_SPLIT__256B 2
- #define SI__TILE_SPLIT__512B 3
- #define SI__TILE_SPLIT__1024B 4
- #define SI__TILE_SPLIT__2048B 5
- #define SI__TILE_SPLIT__4096B 6
- #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
- #define SI__BANK_WIDTH__1 0
- #define SI__BANK_WIDTH__2 1
- #define SI__BANK_WIDTH__4 2
- #define SI__BANK_WIDTH__8 3
- #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
- #define SI__BANK_HEIGHT__1 0
- #define SI__BANK_HEIGHT__2 1
- #define SI__BANK_HEIGHT__4 2
- #define SI__BANK_HEIGHT__8 3
- #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
- #define SI__MACRO_TILE_ASPECT__1 0
- #define SI__MACRO_TILE_ASPECT__2 1
- #define SI__MACRO_TILE_ASPECT__4 2
- #define SI__MACRO_TILE_ASPECT__8 3
- #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
- #define SI__NUM_BANKS__2_BANK 0
- #define SI__NUM_BANKS__4_BANK 1
- #define SI__NUM_BANKS__8_BANK 2
- #define SI__NUM_BANKS__16_BANK 3
- static void si_gb_tile_mode(uint32_t gb_tile_mode,
- unsigned *num_pipes,
- unsigned *num_banks,
- uint32_t *macro_tile_aspect,
- uint32_t *bank_w,
- uint32_t *bank_h,
- uint32_t *tile_split)
- {
- if (num_pipes) {
- switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
- case SI__PIPE_CONFIG__ADDR_SURF_P2:
- default:
- *num_pipes = 2;
- break;
- case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
- case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
- *num_pipes = 4;
- break;
- case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
- case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
- *num_pipes = 8;
- break;
- }
- }
- if (num_banks) {
- switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
- default:
- case SI__NUM_BANKS__2_BANK:
- *num_banks = 2;
- break;
- case SI__NUM_BANKS__4_BANK:
- *num_banks = 4;
- break;
- case SI__NUM_BANKS__8_BANK:
- *num_banks = 8;
- break;
- case SI__NUM_BANKS__16_BANK:
- *num_banks = 16;
- break;
- }
- }
- if (macro_tile_aspect) {
- switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
- default:
- case SI__MACRO_TILE_ASPECT__1:
- *macro_tile_aspect = 1;
- break;
- case SI__MACRO_TILE_ASPECT__2:
- *macro_tile_aspect = 2;
- break;
- case SI__MACRO_TILE_ASPECT__4:
- *macro_tile_aspect = 4;
- break;
- case SI__MACRO_TILE_ASPECT__8:
- *macro_tile_aspect = 8;
- break;
- }
- }
- if (bank_w) {
- switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
- default:
- case SI__BANK_WIDTH__1:
- *bank_w = 1;
- break;
- case SI__BANK_WIDTH__2:
- *bank_w = 2;
- break;
- case SI__BANK_WIDTH__4:
- *bank_w = 4;
- break;
- case SI__BANK_WIDTH__8:
- *bank_w = 8;
- break;
- }
- }
- if (bank_h) {
- switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
- default:
- case SI__BANK_HEIGHT__1:
- *bank_h = 1;
- break;
- case SI__BANK_HEIGHT__2:
- *bank_h = 2;
- break;
- case SI__BANK_HEIGHT__4:
- *bank_h = 4;
- break;
- case SI__BANK_HEIGHT__8:
- *bank_h = 8;
- break;
- }
- }
- if (tile_split) {
- switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
- default:
- case SI__TILE_SPLIT__64B:
- *tile_split = 64;
- break;
- case SI__TILE_SPLIT__128B:
- *tile_split = 128;
- break;
- case SI__TILE_SPLIT__256B:
- *tile_split = 256;
- break;
- case SI__TILE_SPLIT__512B:
- *tile_split = 512;
- break;
- case SI__TILE_SPLIT__1024B:
- *tile_split = 1024;
- break;
- case SI__TILE_SPLIT__2048B:
- *tile_split = 2048;
- break;
- case SI__TILE_SPLIT__4096B:
- *tile_split = 4096;
- break;
- }
- }
- }
- static int si_init_hw_info(struct radeon_surface_manager *surf_man)
- {
- uint32_t tiling_config;
- drmVersionPtr version;
- int r;
- r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
- &tiling_config);
- if (r) {
- return r;
- }
- surf_man->hw_info.allow_2d = 0;
- version = drmGetVersion(surf_man->fd);
- if (version && version->version_minor >= 33) {
- if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
- surf_man->hw_info.allow_2d = 1;
- }
- }
- drmFreeVersion(version);
- switch (tiling_config & 0xf) {
- case 0:
- surf_man->hw_info.num_pipes = 1;
- break;
- case 1:
- surf_man->hw_info.num_pipes = 2;
- break;
- case 2:
- surf_man->hw_info.num_pipes = 4;
- break;
- case 3:
- surf_man->hw_info.num_pipes = 8;
- break;
- default:
- surf_man->hw_info.num_pipes = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf0) >> 4) {
- case 0:
- surf_man->hw_info.num_banks = 4;
- break;
- case 1:
- surf_man->hw_info.num_banks = 8;
- break;
- case 2:
- surf_man->hw_info.num_banks = 16;
- break;
- default:
- surf_man->hw_info.num_banks = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf00) >> 8) {
- case 0:
- surf_man->hw_info.group_bytes = 256;
- break;
- case 1:
- surf_man->hw_info.group_bytes = 512;
- break;
- default:
- surf_man->hw_info.group_bytes = 256;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf000) >> 12) {
- case 0:
- surf_man->hw_info.row_size = 1024;
- break;
- case 1:
- surf_man->hw_info.row_size = 2048;
- break;
- case 2:
- surf_man->hw_info.row_size = 4096;
- break;
- default:
- surf_man->hw_info.row_size = 4096;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- return 0;
- }
- static int si_surface_sanity(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
- {
- uint32_t gb_tile_mode;
- /* check surface dimension */
- if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
- return -EINVAL;
- }
- /* check mipmap last_level */
- if (surf->last_level > 15) {
- return -EINVAL;
- }
- /* force 1d on kernel that can't do 2d */
- if (mode > RADEON_SURF_MODE_1D &&
- (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
- if (surf->nsamples > 1) {
- fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
- return -EFAULT;
- }
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(mode, MODE);
- }
- if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
- return -EINVAL;
- }
- if (!surf->tile_split) {
- /* default value */
- surf->mtilea = 1;
- surf->bankw = 1;
- surf->bankh = 1;
- surf->tile_split = 64;
- surf->stencil_tile_split = 64;
- }
- switch (mode) {
- case RADEON_SURF_MODE_2D:
- if (surf->flags & RADEON_SURF_SBUFFER) {
- switch (surf->nsamples) {
- case 1:
- *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
- break;
- case 2:
- *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
- break;
- case 4:
- *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
- break;
- case 8:
- *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
- break;
- default:
- return -EINVAL;
- }
- /* retrieve tiling mode value */
- gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
- si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
- }
- if (surf->flags & RADEON_SURF_ZBUFFER) {
- switch (surf->nsamples) {
- case 1:
- *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
- break;
- case 2:
- *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
- break;
- case 4:
- *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
- break;
- case 8:
- *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
- break;
- default:
- return -EINVAL;
- }
- } else if (surf->flags & RADEON_SURF_SCANOUT) {
- switch (surf->bpe) {
- case 2:
- *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
- break;
- case 4:
- *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
- break;
- default:
- return -EINVAL;
- }
- } else {
- switch (surf->bpe) {
- case 1:
- *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
- break;
- case 2:
- *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
- break;
- case 4:
- *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
- break;
- case 8:
- case 16:
- *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
- break;
- default:
- return -EINVAL;
- }
- }
- /* retrieve tiling mode value */
- gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
- si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
- break;
- case RADEON_SURF_MODE_1D:
- if (surf->flags & RADEON_SURF_SBUFFER) {
- *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
- }
- if (surf->flags & RADEON_SURF_ZBUFFER) {
- *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
- } else if (surf->flags & RADEON_SURF_SCANOUT) {
- *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
- } else {
- *tile_mode = SI_TILE_MODE_COLOR_1D;
- }
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- default:
- *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
- }
- return 0;
- }
- static void si_surf_minify(struct radeon_surface *surf,
- struct radeon_surface_level *surflevel,
- unsigned bpe, unsigned level,
- uint32_t xalign, uint32_t yalign, uint32_t zalign,
- uint32_t slice_align, uint64_t offset)
- {
- if (level == 0) {
- surflevel->npix_x = surf->npix_x;
- } else {
- surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
- }
- surflevel->npix_y = mip_minify(surf->npix_y, level);
- surflevel->npix_z = mip_minify(surf->npix_z, level);
- if (level == 0 && surf->last_level > 0) {
- surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
- } else {
- surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
- }
- surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
- /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
- * these are just guesses for the rules behind those
- */
- if (level == 0 && surf->last_level == 0)
- /* Non-mipmap pitch padded to slice alignment */
- /* Using just bpe here breaks stencil blitting; surf->bpe works. */
- xalign = MAX2(xalign, slice_align / surf->bpe);
- else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
- /* Small rows evenly distributed across slice */
- xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
- surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
- surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
- surflevel->offset = offset;
- surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
- surflevel->slice_size = ALIGN((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y,
- (uint64_t)slice_align);
- surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
- }
- static void si_surf_minify_2d(struct radeon_surface *surf,
- struct radeon_surface_level *surflevel,
- unsigned bpe, unsigned level, unsigned slice_pt,
- uint32_t xalign, uint32_t yalign, uint32_t zalign,
- unsigned mtileb, uint64_t offset)
- {
- unsigned mtile_pr, mtile_ps;
- if (level == 0) {
- surflevel->npix_x = surf->npix_x;
- } else {
- surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
- }
- surflevel->npix_y = mip_minify(surf->npix_y, level);
- surflevel->npix_z = mip_minify(surf->npix_z, level);
- if (level == 0 && surf->last_level > 0) {
- surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
- } else {
- surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
- surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
- surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
- }
- if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
- !(surf->flags & RADEON_SURF_FMASK)) {
- if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
- surflevel->mode = RADEON_SURF_MODE_1D;
- return;
- }
- }
- surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
- surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
- surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
- /* macro tile per row */
- mtile_pr = surflevel->nblk_x / xalign;
- /* macro tile per slice */
- mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
- surflevel->offset = offset;
- surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
- surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
- surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
- }
- static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned tile_mode,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign, slice_align;
- unsigned i;
- /* compute alignment */
- if (!start_level) {
- surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
- }
- xalign = MAX2(8, 64 / surf->bpe);
- yalign = 1;
- zalign = 1;
- slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
- si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, surf->bo_alignment);
- }
- if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
- surf->tiling_index[i] = tile_mode;
- }
- }
- return 0;
- }
- static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- struct radeon_surface_level *level,
- unsigned bpe, unsigned tile_mode,
- uint64_t offset, unsigned start_level)
- {
- uint32_t xalign, yalign, zalign, slice_align;
- unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
- unsigned i;
- /* compute alignment */
- xalign = 8;
- yalign = 8;
- zalign = 1;
- slice_align = surf_man->hw_info.group_bytes;
- if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
- }
- if (start_level <= 1) {
- surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
- if (offset) {
- offset = ALIGN(offset, alignment);
- }
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- level[i].mode = RADEON_SURF_MODE_1D;
- si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
- /* level0 and first mipmap need to have alignment */
- offset = surf->bo_size;
- if (i == 0) {
- offset = ALIGN(offset, alignment);
- }
- if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
- if (surf->level == level) {
- surf->tiling_index[i] = tile_mode;
- /* it's ok because stencil is done after */
- surf->stencil_tiling_index[i] = tile_mode;
- } else {
- surf->stencil_tiling_index[i] = tile_mode;
- }
- }
- }
- return 0;
- }
- static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned tile_mode, unsigned stencil_tile_mode)
- {
- int r;
- r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
- if (r) {
- return r;
- }
- if (surf->flags & RADEON_SURF_SBUFFER) {
- r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
- surf->stencil_offset = surf->stencil_level[0].offset;
- }
- return r;
- }
- static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- struct radeon_surface_level *level,
- unsigned bpe, unsigned tile_mode,
- unsigned num_pipes, unsigned num_banks,
- unsigned tile_split,
- uint64_t offset,
- unsigned start_level)
- {
- uint64_t aligned_offset = offset;
- unsigned tilew, tileh, tileb;
- unsigned mtilew, mtileh, mtileb;
- unsigned slice_pt;
- unsigned i;
- /* compute tile values */
- tilew = 8;
- tileh = 8;
- tileb = tilew * tileh * bpe * surf->nsamples;
- /* slices per tile */
- slice_pt = 1;
- if (tileb > tile_split && tile_split) {
- slice_pt = tileb / tile_split;
- }
- tileb = tileb / slice_pt;
- /* macro tile width & height */
- mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
- mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
- /* macro tile bytes */
- mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
- if (start_level <= 1) {
- unsigned alignment = MAX2(256, mtileb);
- surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
- if (aligned_offset) {
- aligned_offset = ALIGN(aligned_offset, alignment);
- }
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- level[i].mode = RADEON_SURF_MODE_2D;
- si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
- if (level[i].mode == RADEON_SURF_MODE_1D) {
- switch (tile_mode) {
- case SI_TILE_MODE_COLOR_2D_8BPP:
- case SI_TILE_MODE_COLOR_2D_16BPP:
- case SI_TILE_MODE_COLOR_2D_32BPP:
- case SI_TILE_MODE_COLOR_2D_64BPP:
- tile_mode = SI_TILE_MODE_COLOR_1D;
- break;
- case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
- case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
- tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
- break;
- case SI_TILE_MODE_DEPTH_STENCIL_2D:
- tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
- break;
- default:
- return -EINVAL;
- }
- return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
- }
- /* level0 and first mipmap need to have alignment */
- aligned_offset = offset = surf->bo_size;
- if (i == 0) {
- aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
- }
- if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
- if (surf->level == level) {
- surf->tiling_index[i] = tile_mode;
- /* it's ok because stencil is done after */
- surf->stencil_tiling_index[i] = tile_mode;
- } else {
- surf->stencil_tiling_index[i] = tile_mode;
- }
- }
- }
- return 0;
- }
- static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned tile_mode, unsigned stencil_tile_mode)
- {
- unsigned num_pipes, num_banks;
- uint32_t gb_tile_mode;
- int r;
- /* retrieve tiling mode value */
- gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
- si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
- r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
- if (r) {
- return r;
- }
- if (surf->flags & RADEON_SURF_SBUFFER) {
- r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
- surf->stencil_offset = surf->stencil_level[0].offset;
- }
- return r;
- }
- static int si_surface_init(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, tile_mode, stencil_tile_mode;
- int r;
- /* MSAA surfaces support the 2D mode only. */
- if (surf->nsamples > 1) {
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
- /* zbuffer only support 1D or 2D tiled surface */
- switch (mode) {
- case RADEON_SURF_MODE_1D:
- case RADEON_SURF_MODE_2D:
- break;
- default:
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- break;
- }
- }
- r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
- if (r) {
- return r;
- }
- surf->stencil_offset = 0;
- surf->bo_alignment = 0;
- /* check tiling mode */
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR:
- r = r6_surface_init_linear(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
- break;
- case RADEON_SURF_MODE_1D:
- r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
- break;
- case RADEON_SURF_MODE_2D:
- r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
- break;
- default:
- return -EINVAL;
- }
- return r;
- }
- /*
- * depending on surface
- */
- static int si_surface_best(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, tile_mode, stencil_tile_mode;
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
- !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
- /* depth/stencil force 1d tiling for old mesa */
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- }
- return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
- }
- /* ===========================================================================
- * Sea Islands family
- */
- #define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
- #define CIK__PIPE_CONFIG__ADDR_SURF_P2 0
- #define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
- #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
- #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
- #define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
- #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
- #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16
- #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17
- #define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
- #define CIK__TILE_SPLIT__64B 0
- #define CIK__TILE_SPLIT__128B 1
- #define CIK__TILE_SPLIT__256B 2
- #define CIK__TILE_SPLIT__512B 3
- #define CIK__TILE_SPLIT__1024B 4
- #define CIK__TILE_SPLIT__2048B 5
- #define CIK__TILE_SPLIT__4096B 6
- #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3)
- #define CIK__SAMPLE_SPLIT__1 0
- #define CIK__SAMPLE_SPLIT__2 1
- #define CIK__SAMPLE_SPLIT__4 2
- #define CIK__SAMPLE_SPLIT__8 3
- #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3)
- #define CIK__BANK_WIDTH__1 0
- #define CIK__BANK_WIDTH__2 1
- #define CIK__BANK_WIDTH__4 2
- #define CIK__BANK_WIDTH__8 3
- #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3)
- #define CIK__BANK_HEIGHT__1 0
- #define CIK__BANK_HEIGHT__2 1
- #define CIK__BANK_HEIGHT__4 2
- #define CIK__BANK_HEIGHT__8 3
- #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
- #define CIK__MACRO_TILE_ASPECT__1 0
- #define CIK__MACRO_TILE_ASPECT__2 1
- #define CIK__MACRO_TILE_ASPECT__4 2
- #define CIK__MACRO_TILE_ASPECT__8 3
- #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3)
- #define CIK__NUM_BANKS__2_BANK 0
- #define CIK__NUM_BANKS__4_BANK 1
- #define CIK__NUM_BANKS__8_BANK 2
- #define CIK__NUM_BANKS__16_BANK 3
- static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
- unsigned bpe, unsigned nsamples, bool is_color,
- unsigned tile_mode,
- uint32_t *num_pipes,
- uint32_t *tile_split_ptr,
- uint32_t *num_banks,
- uint32_t *macro_tile_aspect,
- uint32_t *bank_w,
- uint32_t *bank_h)
- {
- uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
- unsigned tileb_1x, tileb;
- unsigned gb_macrotile_mode;
- unsigned macrotile_index;
- unsigned tile_split, sample_split;
- if (num_pipes) {
- switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
- case CIK__PIPE_CONFIG__ADDR_SURF_P2:
- default:
- *num_pipes = 2;
- break;
- case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
- case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
- *num_pipes = 4;
- break;
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
- case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
- *num_pipes = 8;
- break;
- case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
- case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
- *num_pipes = 16;
- break;
- }
- }
- switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
- default:
- case CIK__TILE_SPLIT__64B:
- tile_split = 64;
- break;
- case CIK__TILE_SPLIT__128B:
- tile_split = 128;
- break;
- case CIK__TILE_SPLIT__256B:
- tile_split = 256;
- break;
- case CIK__TILE_SPLIT__512B:
- tile_split = 512;
- break;
- case CIK__TILE_SPLIT__1024B:
- tile_split = 1024;
- break;
- case CIK__TILE_SPLIT__2048B:
- tile_split = 2048;
- break;
- case CIK__TILE_SPLIT__4096B:
- tile_split = 4096;
- break;
- }
- switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
- default:
- case CIK__SAMPLE_SPLIT__1:
- sample_split = 1;
- break;
- case CIK__SAMPLE_SPLIT__2:
- sample_split = 2;
- break;
- case CIK__SAMPLE_SPLIT__4:
- sample_split = 4;
- break;
- case CIK__SAMPLE_SPLIT__8:
- sample_split = 8;
- break;
- }
- /* Adjust the tile split. */
- tileb_1x = 8 * 8 * bpe;
- if (is_color) {
- tile_split = MAX2(256, sample_split * tileb_1x);
- }
- tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
- /* Determine the macrotile index. */
- tileb = MIN2(tile_split, nsamples * tileb_1x);
- for (macrotile_index = 0; tileb > 64; macrotile_index++) {
- tileb >>= 1;
- }
- gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
- if (tile_split_ptr) {
- *tile_split_ptr = tile_split;
- }
- if (num_banks) {
- switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
- default:
- case CIK__NUM_BANKS__2_BANK:
- *num_banks = 2;
- break;
- case CIK__NUM_BANKS__4_BANK:
- *num_banks = 4;
- break;
- case CIK__NUM_BANKS__8_BANK:
- *num_banks = 8;
- break;
- case CIK__NUM_BANKS__16_BANK:
- *num_banks = 16;
- break;
- }
- }
- if (macro_tile_aspect) {
- switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
- default:
- case CIK__MACRO_TILE_ASPECT__1:
- *macro_tile_aspect = 1;
- break;
- case CIK__MACRO_TILE_ASPECT__2:
- *macro_tile_aspect = 2;
- break;
- case CIK__MACRO_TILE_ASPECT__4:
- *macro_tile_aspect = 4;
- break;
- case CIK__MACRO_TILE_ASPECT__8:
- *macro_tile_aspect = 8;
- break;
- }
- }
- if (bank_w) {
- switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
- default:
- case CIK__BANK_WIDTH__1:
- *bank_w = 1;
- break;
- case CIK__BANK_WIDTH__2:
- *bank_w = 2;
- break;
- case CIK__BANK_WIDTH__4:
- *bank_w = 4;
- break;
- case CIK__BANK_WIDTH__8:
- *bank_w = 8;
- break;
- }
- }
- if (bank_h) {
- switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
- default:
- case CIK__BANK_HEIGHT__1:
- *bank_h = 1;
- break;
- case CIK__BANK_HEIGHT__2:
- *bank_h = 2;
- break;
- case CIK__BANK_HEIGHT__4:
- *bank_h = 4;
- break;
- case CIK__BANK_HEIGHT__8:
- *bank_h = 8;
- break;
- }
- }
- }
- static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
- {
- uint32_t tiling_config;
- drmVersionPtr version;
- int r;
- r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
- &tiling_config);
- if (r) {
- return r;
- }
- surf_man->hw_info.allow_2d = 0;
- version = drmGetVersion(surf_man->fd);
- if (version && version->version_minor >= 35) {
- if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
- !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
- surf_man->hw_info.allow_2d = 1;
- }
- }
- drmFreeVersion(version);
- switch (tiling_config & 0xf) {
- case 0:
- surf_man->hw_info.num_pipes = 1;
- break;
- case 1:
- surf_man->hw_info.num_pipes = 2;
- break;
- case 2:
- surf_man->hw_info.num_pipes = 4;
- break;
- case 3:
- surf_man->hw_info.num_pipes = 8;
- break;
- default:
- surf_man->hw_info.num_pipes = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf0) >> 4) {
- case 0:
- surf_man->hw_info.num_banks = 4;
- break;
- case 1:
- surf_man->hw_info.num_banks = 8;
- break;
- case 2:
- surf_man->hw_info.num_banks = 16;
- break;
- default:
- surf_man->hw_info.num_banks = 8;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf00) >> 8) {
- case 0:
- surf_man->hw_info.group_bytes = 256;
- break;
- case 1:
- surf_man->hw_info.group_bytes = 512;
- break;
- default:
- surf_man->hw_info.group_bytes = 256;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- switch ((tiling_config & 0xf000) >> 12) {
- case 0:
- surf_man->hw_info.row_size = 1024;
- break;
- case 1:
- surf_man->hw_info.row_size = 2048;
- break;
- case 2:
- surf_man->hw_info.row_size = 4096;
- break;
- default:
- surf_man->hw_info.row_size = 4096;
- surf_man->hw_info.allow_2d = 0;
- break;
- }
- return 0;
- }
- static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
- {
- /* check surface dimension */
- if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
- return -EINVAL;
- }
- /* check mipmap last_level */
- if (surf->last_level > 15) {
- return -EINVAL;
- }
- /* force 1d on kernel that can't do 2d */
- if (mode > RADEON_SURF_MODE_1D &&
- (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
- if (surf->nsamples > 1) {
- fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
- return -EFAULT;
- }
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(mode, MODE);
- }
- if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
- return -EINVAL;
- }
- if (!surf->tile_split) {
- /* default value */
- surf->mtilea = 1;
- surf->bankw = 1;
- surf->bankh = 1;
- surf->tile_split = 64;
- surf->stencil_tile_split = 64;
- }
- switch (mode) {
- case RADEON_SURF_MODE_2D: {
- if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
- switch (surf->nsamples) {
- case 1:
- *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
- break;
- case 2:
- case 4:
- *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
- break;
- case 8:
- *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
- break;
- default:
- return -EINVAL;
- }
- if (surf->flags & RADEON_SURF_SBUFFER) {
- *stencil_tile_mode = *tile_mode;
- cik_get_2d_params(surf_man, 1, surf->nsamples, false,
- *stencil_tile_mode, NULL,
- &surf->stencil_tile_split,
- NULL, NULL, NULL, NULL);
- }
- } else if (surf->flags & RADEON_SURF_SCANOUT) {
- *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
- } else {
- *tile_mode = CIK_TILE_MODE_COLOR_2D;
- }
- /* retrieve tiling mode values */
- cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
- !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
- NULL, &surf->tile_split, NULL, &surf->mtilea,
- &surf->bankw, &surf->bankh);
- break;
- }
- case RADEON_SURF_MODE_1D:
- if (surf->flags & RADEON_SURF_SBUFFER) {
- *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
- }
- if (surf->flags & RADEON_SURF_ZBUFFER) {
- *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
- } else if (surf->flags & RADEON_SURF_SCANOUT) {
- *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
- } else {
- *tile_mode = SI_TILE_MODE_COLOR_1D;
- }
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- default:
- *stencil_tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
- *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
- }
- return 0;
- }
- static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- struct radeon_surface_level *level,
- unsigned bpe, unsigned tile_mode,
- unsigned tile_split,
- unsigned num_pipes, unsigned num_banks,
- uint64_t offset,
- unsigned start_level)
- {
- uint64_t aligned_offset = offset;
- unsigned tilew, tileh, tileb_1x, tileb;
- unsigned mtilew, mtileh, mtileb;
- unsigned slice_pt;
- unsigned i;
- /* compute tile values */
- tilew = 8;
- tileh = 8;
- tileb_1x = tilew * tileh * bpe;
- tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
- tileb = surf->nsamples * tileb_1x;
- /* slices per tile */
- slice_pt = 1;
- if (tileb > tile_split && tile_split) {
- slice_pt = tileb / tile_split;
- tileb = tileb / slice_pt;
- }
- /* macro tile width & height */
- mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
- mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
- /* macro tile bytes */
- mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
- if (start_level <= 1) {
- unsigned alignment = MAX2(256, mtileb);
- surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
- if (aligned_offset) {
- aligned_offset = ALIGN(aligned_offset, alignment);
- }
- }
- /* build mipmap tree */
- for (i = start_level; i <= surf->last_level; i++) {
- level[i].mode = RADEON_SURF_MODE_2D;
- si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
- if (level[i].mode == RADEON_SURF_MODE_1D) {
- switch (tile_mode) {
- case CIK_TILE_MODE_COLOR_2D:
- tile_mode = SI_TILE_MODE_COLOR_1D;
- break;
- case CIK_TILE_MODE_COLOR_2D_SCANOUT:
- tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
- break;
- case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
- case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
- case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
- case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
- case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
- tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
- break;
- default:
- return -EINVAL;
- }
- return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
- }
- /* level0 and first mipmap need to have alignment */
- aligned_offset = offset = surf->bo_size;
- if (i == 0) {
- aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
- }
- if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
- if (surf->level == level) {
- surf->tiling_index[i] = tile_mode;
- /* it's ok because stencil is done after */
- surf->stencil_tiling_index[i] = tile_mode;
- } else {
- surf->stencil_tiling_index[i] = tile_mode;
- }
- }
- }
- return 0;
- }
- static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned tile_mode, unsigned stencil_tile_mode)
- {
- int r;
- uint32_t num_pipes, num_banks;
- cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
- !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
- &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
- r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
- surf->tile_split, num_pipes, num_banks, 0, 0);
- if (r) {
- return r;
- }
- if (surf->flags & RADEON_SURF_SBUFFER) {
- r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
- surf->stencil_tile_split, num_pipes, num_banks,
- surf->bo_size, 0);
- surf->stencil_offset = surf->stencil_level[0].offset;
- }
- return r;
- }
- static int cik_surface_init(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, tile_mode, stencil_tile_mode;
- int r;
- /* MSAA surfaces support the 2D mode only. */
- if (surf->nsamples > 1) {
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
- /* zbuffer only support 1D or 2D tiled surface */
- switch (mode) {
- case RADEON_SURF_MODE_1D:
- case RADEON_SURF_MODE_2D:
- break;
- default:
- mode = RADEON_SURF_MODE_1D;
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- break;
- }
- }
- r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
- if (r) {
- return r;
- }
- surf->stencil_offset = 0;
- surf->bo_alignment = 0;
- /* check tiling mode */
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR:
- r = r6_surface_init_linear(surf_man, surf, 0, 0);
- break;
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
- break;
- case RADEON_SURF_MODE_1D:
- r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
- break;
- case RADEON_SURF_MODE_2D:
- r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
- break;
- default:
- return -EINVAL;
- }
- return r;
- }
- /*
- * depending on surface
- */
- static int cik_surface_best(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, tile_mode, stencil_tile_mode;
- /* tiling mode */
- mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
- !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
- /* depth/stencil force 1d tiling for old mesa */
- surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
- surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- }
- return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
- }
- /* ===========================================================================
- * public API
- */
- drm_public struct radeon_surface_manager *
- radeon_surface_manager_new(int fd)
- {
- struct radeon_surface_manager *surf_man;
- surf_man = calloc(1, sizeof(struct radeon_surface_manager));
- if (surf_man == NULL) {
- return NULL;
- }
- surf_man->fd = fd;
- if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
- goto out_err;
- }
- if (radeon_get_family(surf_man)) {
- goto out_err;
- }
- if (surf_man->family <= CHIP_RV740) {
- if (r6_init_hw_info(surf_man)) {
- goto out_err;
- }
- surf_man->surface_init = &r6_surface_init;
- surf_man->surface_best = &r6_surface_best;
- } else if (surf_man->family <= CHIP_ARUBA) {
- if (eg_init_hw_info(surf_man)) {
- goto out_err;
- }
- surf_man->surface_init = &eg_surface_init;
- surf_man->surface_best = &eg_surface_best;
- } else if (surf_man->family < CHIP_BONAIRE) {
- if (si_init_hw_info(surf_man)) {
- goto out_err;
- }
- surf_man->surface_init = &si_surface_init;
- surf_man->surface_best = &si_surface_best;
- } else {
- if (cik_init_hw_info(surf_man)) {
- goto out_err;
- }
- surf_man->surface_init = &cik_surface_init;
- surf_man->surface_best = &cik_surface_best;
- }
- return surf_man;
- out_err:
- free(surf_man);
- return NULL;
- }
- drm_public void
- radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
- {
- free(surf_man);
- }
- static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf,
- unsigned type,
- unsigned mode)
- {
- if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
- return -EINVAL;
- }
- /* all dimension must be at least 1 ! */
- if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
- return -EINVAL;
- }
- if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
- return -EINVAL;
- }
- if (!surf->array_size) {
- return -EINVAL;
- }
- /* array size must be a power of 2 */
- surf->array_size = next_power_of_two(surf->array_size);
- switch (surf->nsamples) {
- case 1:
- case 2:
- case 4:
- case 8:
- break;
- default:
- return -EINVAL;
- }
- /* check type */
- switch (type) {
- case RADEON_SURF_TYPE_1D:
- if (surf->npix_y > 1) {
- return -EINVAL;
- }
- /* fallthrough */
- case RADEON_SURF_TYPE_2D:
- if (surf->npix_z > 1) {
- return -EINVAL;
- }
- break;
- case RADEON_SURF_TYPE_CUBEMAP:
- if (surf->npix_z > 1) {
- return -EINVAL;
- }
- /* deal with cubemap as they were texture array */
- if (surf_man->family >= CHIP_RV770) {
- surf->array_size = 8;
- } else {
- surf->array_size = 6;
- }
- break;
- case RADEON_SURF_TYPE_3D:
- break;
- case RADEON_SURF_TYPE_1D_ARRAY:
- if (surf->npix_y > 1) {
- return -EINVAL;
- }
- case RADEON_SURF_TYPE_2D_ARRAY:
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- drm_public int
- radeon_surface_init(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, type;
- int r;
- type = RADEON_SURF_GET(surf->flags, TYPE);
- mode = RADEON_SURF_GET(surf->flags, MODE);
- r = radeon_surface_sanity(surf_man, surf, type, mode);
- if (r) {
- return r;
- }
- return surf_man->surface_init(surf_man, surf);
- }
- drm_public int
- radeon_surface_best(struct radeon_surface_manager *surf_man,
- struct radeon_surface *surf)
- {
- unsigned mode, type;
- int r;
- type = RADEON_SURF_GET(surf->flags, TYPE);
- mode = RADEON_SURF_GET(surf->flags, MODE);
- r = radeon_surface_sanity(surf_man, surf, type, mode);
- if (r) {
- return r;
- }
- return surf_man->surface_best(surf_man, surf);
- }
|